简体   繁体   English

WP7 从 Tombstone 恢复并返回页面

[英]WP7 recover from Tombstone and return to page

Is there an nice / elegant way to get back to the page a user was on when recovering from a tombstone?从墓碑中恢复时,是否有一种很好/优雅的方式可以返回用户所在的页面? I'm not sure if my app or its just the way things work, but I always end up back on my Main page.我不确定我的应用程序还是它的工作方式,但我总是回到我的主页。

My app is setup with a main page that has a Pivot Control and several of the Pivot Items will navigate to new pages.我的应用程序设置有一个主页,该主页具有 Pivot 控件和几个 Pivot 项目将导航到新页面。 My Naigation looks something like this if it makes sense:如果有意义的话,我的 Naigation 看起来像这样:

PivotItem1 -> PageA PivotItem1 -> PageA
PivotItem2 -> PageB -> PageC PivotItem2 -> PageB -> PageC
PivotItem3 -> PageD -> PageE - PageF (Pressing Back Button on PageF will use NonLinear Navigation Service back to Main page) PivotItem3 -> PageD -> PageE - PageF(按 PageF 上的返回按钮将使用非线性导航服务返回主页面)

So if the user tombstones on any of the pages I want to return them to that page and have the BackStack available so the navigation doesn't get screwed up.因此,如果用户在任何页面上建立墓碑,我想将它们返回到该页面并让 BackStack 可用,这样导航就不会被搞砸。

I'm using MVVM Light and NonLinear Navigation Service if that helps or hurts what I'm trying to accomplish.我正在使用 MVVM Light 和非线性导航服务,如果这有助于或损害我想要完成的工作。

@Tyler, Cyberherbalist: I regret I cannot just 'add a comment' to your discussion right there. @Tyler,Cyberherbalist:我很遗憾我不能就在你的讨论中“添加评论”。 I'm yet too low on reputation or whatever.我的声誉或其他任何东西都太低了。 I dont have any blog to post it there and give you a link to it, either.我也没有任何博客可以在那里发布并给你一个链接。 I'll just write here, because I think it is worth noticing and writing somewhere, so others may also check/use/permormanceprofit from that.我就写在这里,因为我认为它值得关注和写在某个地方,所以其他人也可能会从中检查/使用/permormanceprofit。

..so, excuse me for this "offtopic article" here:) ..所以,请原谅我的这篇“离题文章”:)

While I don't know how to solve the problem nicely - my solution usually is to collect the navigation history stack by hand, put it into iso, and restore on activation and jump to the right/last place - I can tell you a little bit about the tombstoning.虽然我不知道如何很好地解决问题 - 我的解决方案通常是手动收集导航历史堆栈,将其放入 iso,并在激活时恢复并跳转到正确/最后一个位置 - 我可以告诉你一点关于墓碑的一点。

The matter is, that if your application is deactivated , that does not mean that it is tombstoned.问题是,如果您的应用程序已停用,这并不意味着它已被删除。 Deactivation simply means that your aplication is swapped out of the screen.停用只是意味着您的应用程序被换出屏幕。 In the Mango release, you can tap&hold the "Back" device button and see what applications are opened currently, and jump to any.在 Mango 版本中,您可以点击并按住“返回”设备按钮,查看当前打开了哪些应用程序,然后跳转到任何应用程序。 "Activated" is when your application is woken up. “激活”是您的应用程序被唤醒的时间。 Even in the very early releases of the WP7 SDK+Emulator, I was calling external mediaplayer from my applications, and my applications almost never were physically killed.即使在 WP7 SDK+Emulator 的早期版本中,我也在从我的应用程序中调用外部媒体播放器,而我的应用程序几乎从未被物理杀死。 Deactivated/Activated always resumed my application just right there where it was 'halted'.停用/激活总是在我的应用程序“停止”的地方恢复我的应用程序。 All in-memory objects were untouched.所有内存中的对象都未触及。

Tombstoning occurs when the device is low on resources, and must "kill" some background tasks to free up the memory.当设备资源不足时会发生墓碑,并且必须“杀死”一些后台任务以释放 memory。 I believe it may also occur when the device's screensaver dropsdown, and the device is in standby for a prolonged time.我相信当设备的屏幕保护程序下拉并且设备长时间处于待机状态时也会发生这种情况。 Tombstoning will literally kill your application, all in-memory objects will be destroyed/removed and so on. Tombstoning 将真正杀死您的应用程序,所有内存中的对象都将被销毁/删除等等。 The only thing that will survive is the AppSettings and the ISO store.唯一能幸存下来的是 AppSettings 和 ISO 商店。 Tombstoning is guaranteed to happen ONLY if your application is in deactivated state.当您的应用程序处于停用的 state 时,才会保证发生墓碑。

So, what life-cycles you can see?那么,您可以看到哪些生命周期?

1) "Freeze/Standby/Unfocus": 1)“冻结/待机/散焦”:

  • Launching发射
  • ... (working) ... (在职的)
  • Deactivated (moved to background)停用(移至后台)
  • ... (kept in memory, maybe process/thread is frozen, but I doubt) ...(保留在 memory 中,可能进程/线程被冻结,但我怀疑)
  • (...) (...)
  • Activated (moved to foreground, no navigation occurs)已激活(移至前台,不发生导航)
  • ... (working) ... (在职的)
  • Closing结束

2) "Tombstoned": 2)“墓碑”:

  • Launching发射
  • ... (working) ... (在职的)
  • Deactivated (moved to background)停用(移至后台)
  • ... (kept in memory, maybe process/thread is frozen, but I doubt) ...(保留在 memory 中,可能进程/线程被冻结,但我怀疑)
  • ... (tombstoned, removed from memory, everything destroyed) ...(墓碑,从 memory 中删除,一切都被摧毁)
  • (...) (...)
  • ... (clean application object constructed) ...(清洁应用 object 构建)
  • Activated (moved to foreground)已激活(移至前台)
  • Navigated (I think, always to the first, default page set in the manifest, but I'm not sure now)导航(我认为,总是到清单中设置的第一个默认页面,但我现在不确定)
  • (working) (在职的)
  • Closing结束

This means, that tombstoning may be a little hard to detect, but also means, that you always have a time to try to same your state in the deactivated-eventhandler.这意味着,墓碑化可能有点难以检测,但也意味着您总是有时间尝试在 deactivated-eventhandler 中与您的 state 相同。

This also means, that (unless there is some notification service that I do not know of yet), the only way to detect if a resume-from-tombstone is to rely on... is to rely on the most deadly/unpleasant effect of it: on having your memory purged.这也意味着,(除非有一些我还不知道的通知服务),检测来自墓碑的简历是否依赖...的唯一方法是依赖最致命/不愉快的效果其中:清除您的 memory。

Imagine a simpliest case: your App object has a property "private bool _tomb_test".想象一个最简单的情况:您的应用程序 object 有一个属性“private bool _tomb_test”。 It may be ANY property/field of ANY type.它可以是任何类型的任何属性/字段。 You can use your "object ViewModel{get;set}" as well for that.你也可以使用你的“object ViewModel{get;set}”。

First thing to remember is, NOT to set it in the constructor, and do NOT assign a inline default value.首先要记住的是,不要在构造函数中设置它,也不要分配内联默认值。 Just leave it floating.让它漂浮。 The compiler/runtime will set it to the default false whenever the App object is created freshly new.只要 App object 是全新创建的,编译器/运行时就会将其设置为默认值。 And that's the point!这就是重点!

now:现在:

  • in Launched (not ctor,!!), set "_tomb_test = true"在已启动(不是 ctor,!!)中,设置“_tomb_test = true”
  • in deactivated, save your minimum persistent state to ISO在停用状态下,将您的最小持久性 state 保存到 ISO
  • in activated, check:在激活中,检查:
    • if _tomb_test==false that means, you were tombstoned.如果 _tomb_test==false 这意味着,你被墓碑。 your memory is clean, all objects were destroyed.你的 memory 是干净的,所有物体都被破坏了。 restore your state according to data last written to the ISO, and then start all jobs to refill/redownload/reload/recalculate/etc all the other parts of the app state根据上次写入 ISO 的数据恢复您的 state,然后启动所有作业以重新填充/重新下载/重新加载/重新计算/等应用程序的所有其他部分 state
    • but, if _tomb_test==true, that means that the tombstoning did not occur.但是,如果_tomb_test==true,这意味着墓碑没有发生。 your memory is untouched.您的 memory 未受影响。 maybe just the GC kicked in and collected the dead.也许只是 GC 介入并收集了死者。 all objects that were living are still alive.所有活着的物体都还活着。 the app is free to just run as if nothing ever happened.该应用程序可以免费运行,就好像什么都没发生过一样。

While it may look pretty, please excuse me for this lengthy disclaimer:虽然它看起来很漂亮,但请原谅我这个冗长的免责声明:

I use it successfully in current application with 100% success, but I cannot say that this is guaranteed platform's behaviour.我在当前的应用程序中成功使用它并 100% 成功,但我不能说这是保证平台的行为。 I have yet to find time to dig for the facts on MSDN.我还没有时间在 MSDN 上挖掘事实。 All of the above cames from my observations on the 7.0 and 7.1 SDK releases.以上所有内容均来自我对 7.0 和 7.1 SDK 版本的观察。

The small problem of the above approach is that it relies on the (unproven?) assumption, that the memory purge works in an all-or-nothing fashion.上述方法的小问题是它依赖于(未经证实的?)假设,即 memory 清除以全有或全无的方式工作。

That is, assumes that either all objects are purged, or no purge occurs (current fact: the App object and is observed to be re-created from scratch, and even an initial navigation occurs to recreate the UI. In other cases neither of it happens).也就是说,假设所有对象都被清除,或者没有发生清除(当前事实:应用程序 object 并观察到从头开始重新创建,甚至发生初始导航以重新创建 UI。在其他情况下,两者都没有发生)。

For the assumption to be wrong... I just cannot imagine who and why would ever decide to implement partial memory purge in the .net world.对于错误的假设......我无法想象谁以及为什么会决定在 .net 世界中实施部分 memory 清除。 Full purge means killing the app.完全清除意味着终止应用程序。 Partial purge means destroying random living objects in the GC generations and leaving all the rest alive with dangling handles, or with nulled handles.部分清除意味着破坏 GC 代中的随机活对象,并让所有 rest 保持活动状态,并带有悬垂的句柄或无效的句柄。 I cannot imagine it.我无法想象。 I have not observed it.我没有观察到。 Thus, I assume it's all-or-nothing.因此,我认为这是全有或全无。

BTW.顺便提一句。 If you ever observe a partial purge and find a mostly-deterministic way to cause it, so others may see it too, please broadcast it loudly: :)如果您观察到部分清除并找到一种主要确定的方法来导致它,因此其他人也可能看到它,请大声广播::)

I have a similarly navigation-heavy app out there and it does what you want (also uses NonLinear Navigation Service).我有一个类似的重导航应用程序,它可以满足您的需求(也使用非线性导航服务)。 In my case I store the user's current page/pivot item in isolated storage, along with a token (or bool) indicating whether or not the app is returning from a tombstoning.在我的情况下,我将用户的当前页面/数据透视项目存储在隔离存储中,以及指示应用程序是否从墓碑返回的令牌(或布尔值)。 When the user navigates to a page, the page load sets the current page value in the iso, and if the page has a pivot, it also sets the current pivot to the first one.当用户导航到一个页面时,页面加载设置iso中的当前页面值,如果页面有pivot,它也会将当前pivot设置为第一个。 The pivot_changed event has code to change the new current pivot to one the user just changed to. pivot_changed 事件具有将新的当前 pivot 更改为用户刚刚更改的代码的代码。

When the app is in the process of tombstoning, the app_deactivate event fires, and it is here that I set the IsTombstoned value in iso to true.当应用程序处于墓碑过程中时,会触发 app_deactivate 事件,并且在这里我将 iso 中的 IsTombstoned 值设置为 true。

When the user returns from tombstoning, the main page_load first checks to see if the app is reactivating from being tombstoned (IsTombstoned=true), and if so, it navigates immediately to the page whose name was stored in iso.当用户从墓碑返回时,主 page_load 首先检查应用程序是否正在从墓碑重新激活 (IsTombstoned=true),如果是,它会立即导航到名称存储在 iso 中的页面。 When the now-current page_load fires it checks to see if IsTombstoned=true, and if so, sets it to false (back to normal), and if there's a pivot on the page, sets the selected pivot item to the stored current pivot.当当前的 page_load 触发时,它会检查 IsTombstoned=true,如果是,则将其设置为 false(恢复正常),如果页面上有 pivot,则将选定的 pivot 项设置为存储的当前 ZDCA758FD47F2E975ZBBF。 If the page doesn't have a pivot control, the current pivot is left blank.如果页面没有 pivot 控件,则当前 pivot 将留空。 If there was dynamic content in the page when it was tombstoned, you'll also need to provide for its restoration.如果在被墓碑化时页面中有动态内容,您还需要为其提供恢复。

Sorry I'm not showing you the code, but am away from workstation and I can't get to it.抱歉,我没有向您展示代码,但我远离工作站,我无法使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM