WP7从Tombstone恢复并返回页面

有一种很好/优雅的方式可以回到用户从墓碑中恢复时所处的页面吗? 我不确定我的应用程序或它的工作方式,但我总是回到我的主页面。

我的应用程序设置了一个主页面,其中包含一个Pivot控件,并且几个Pivot项目将导航到新页面。 如果有意义,我的Naigation看起来像这样:

PivotItem1 – > PageA
PivotItem2 – > PageB – > PageC
PivotItem3 – > PageD – > PageE – PageF(PageF上的按下后退按钮将使用NonLinear导航服务返回主页面)

因此,如果任何页面上的用户墓碑我想将它们返回到该页面并且可以使用BackStack,那么导航就不会搞砸了。

我正在使用MVVM Light和NonLinear导航服务,如果这有助于或伤害我正在努力实现的目标。

@Tyler,Cyber​​herbalist:我很遗憾我不能只是在你的讨论中“添加评论”。 我的声誉或其他方面都太低了。 我没有任何博客在那里发布它并给你一个链接。 我只想写在这里,因为我认为值得注意并在某处写作,所以其他人也可以检查/使用/ permormanceprofit。

..那么,请原谅我这里的“offtopic文章”:)

虽然我不知道如何很好地解决问题 – 我的解决方案通常是手动收集导航历史堆栈,将其放入iso,并在激活时恢复并跳转到右侧/最后一个位置 – 我可以告诉您一些关于墓碑的一点点。

问题是,如果您的应用程序被停用 ,那并不意味着它被逻辑删除。 停用只是意味着您的应用程序被换出屏幕。 在Mango版本中,您可以点击并按住“返回”设备按钮,查看当前打开的应用程序,然后跳转到任何应用程序。 “激活”是您的应用程序被唤醒的时间。 即使在WP7 SDK + Emulator的早期版本中,我也是从我的应用程序调用外部媒体播放器,而我的应用程序几乎从未被人类杀死过。 Deactivated / Activated总是恢复我的应用程序就在那里’停止’。 所有内存中的对象都没有受到影响。

当设备资源不足时发生逻辑删除,并且必须“杀死”某些后台任务以释放内存。 我相信当设备的屏幕保护程序下降,并且设备处于待机状态较长时间时,也可能发生这种情况。 Tombstoning将直接杀死您的应用程序,所有内存中的对象将被销毁/删除等等。 唯一能够存活的是AppSettings和ISO商店。 只有当您的应用程序处于停用状态时,才能保证逻辑删除。

那么,你可以看到什么样的生命周期?

1)“冻结/待机/取消聚焦”:

  • 发射
  • ……(工作)
  • 已停用(移至后台)
  • …(保留在内存中,也许进程/线程被冻结,但我怀疑)
  • (……)
  • 已激活(移至前台,未进行导航)
  • ……(工作)
  • 闭幕

2)“Tombstoned”:

  • 发射
  • ……(工作)
  • 已停用(移至后台)
  • …(保留在内存中,也许进程/线程被冻结,但我怀疑)
  • …(墓碑,从记忆中移除,一切都被毁坏)
  • (……)
  • …(构建清洁应用程序对象)
  • 已激活(移至前台)
  • 导航(我想,总是在清单中设置第一个默认页面,但我现在不确定)
  • (工作)
  • 闭幕

这意味着,墓碑可能有点难以检测,但也意味着您总是有时间尝试在停用事件处理程序中使用相同的状态。

这也意味着(除非有一些我还不知道的通知服务),检测从墓碑中恢复是否依赖的唯一方法是依靠最致命/不愉快的效果它:清除你的记忆。

想象一个最简单的情况:你的App对象有一个属性“private bool _tomb_test”。 它可能是任何类型的任何属性/字段。 您也可以使用“对象ViewModel {get; set}”。

首先要记住的是, 不要在构造函数中设置它,也不要指定内联默认值。 让它漂浮。 每当App对象新创建时,编译器/运行时都会将其设置为默认值false。 这就是重点!

现在:

  • 在发布(不是ctor !!!)中,设置“_tomb_test = true”
  • 在停用时,将最小持久状态保存到ISO
  • 在激活,检查:
    • 如果_tomb_test == false这意味着你被墓碑化了。 你的记忆很干净,所有物品都被摧毁了。 根据最后写入ISO的数据恢复您的状态,然后启动所有作业以重新填充/重新下载/重新加载/重新计算/等应用程序状态的所有其他部分
    • 但是,如果_tomb_test == true,这意味着墓碑没有发生。 你的记忆没有受到影响。 也许只是GC开始并收集了死者。 所有生活的对象仍然活着。 该应用程序可以自由运行,好像什么都没发生过一样。

虽然看起来很漂亮,但请原谅我这篇冗长的免责声明:

我在目前的应用程序中成功使用它取得了100%的成功,但我不能说这是保证平台的行为。 我还没有时间在MSDN上挖掘事实。 以上所有内容都来自我对7.0和7.1 SDK版本的观察。

上述方法的一个小问题是它依赖于(未经证实的)假设,即内存清除以全有或全无的方式工作。

也就是说,假设所有对象都被清除,或者没有发生清除(当前事实:App对象被观察到从头开始重新创建,甚至初始导航也会重新创建UI。在其他情况下,它都不是发生)。

假设是错误的…我无法想象谁和为什么决定在.net世界中实现部分内存清除。 完全清除意味着杀死应用程序。 部分清除意味着在GC世代中摧毁随机生物,并将所有其余物体留在悬挂手柄或带有无效手柄的位置。 我无法想象。 我没有观察到它。 因此,我认为它是全有或全无的。

BTW。 如果你曾经观察到部分清除并找到一种主要确定性的方法来引起它,那么其他人也可能会看到它,请大声播放! 🙂

我有一个类似的导航重的应用程序,它做你想要的(也使用NonLinear导航服务)。 在我的情况下,我将用户的当前页面/枢轴项目存储在隔离存储中,以及指示应用程序是否从逻辑删除返回的令牌(或bool)。 当用户导航到页面时,页面加载会在iso中设置当前页面值,如果页面有一个数据透视表,它还会将当前数据透视表设置为第一个。 pivot_changed事件具有将新的当前数据透视更改为刚刚更改为的用户的代码。

当应用程序处于逻辑删除过程中时,会触发app_deactivate事件,并且我在此处将iso中的IsTombstoned值设置为true。

当用户从逻辑删除返回时,主page_load首先检查应用程序是否从逻辑删除重新激活(IsTombstoned = true),如果是,则立即导航到名称存储在iso中的页面。 当前当前的page_load触发时,它会检查是否IsTombstoned = true,如果是,则将其设置为false(恢复正常),如果页面上有一个pivot,则将选定的pivot项设置为存储的当前pivot。 如果页面没有枢轴控件,则当前轴将保留为空白。 如果在逻辑删除时页面中存在动态内容,您还需要提供其恢复。

对不起,我没有向您展示代码,但我远离工作站,我无法达到它。