WP7从Tombstone恢复并返回页面
从逻辑删除恢复时,是否有一种很好/优雅的方式返回用户所在的页面?我不确定我的应用程序是否正常工作,但我总是回到我的主页。
我的应用程序设置了一个带有枢轴控件的主页,并且多个枢轴项目将导航到新页面。如果有意义的话,我的导航看起来像这样:
PivotItem1 ->页A
数据透视项2 -> B页-> C页
PivotItem3 ->; D页-> PageE - PageF(按 PageF 上的后退按钮将使用非线性导航服务返回主页)
因此,如果用户在任何页面上建立墓碑,我希望将它们返回到该页面并让 BackStack 可用,这样导航就不会被搞砸向上。
我正在使用 MVVM Light 和非线性导航服务,如果这有助于或损害我想要完成的任务。
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. My Naigation looks something like this if it makes sense:
PivotItem1 -> PageA
PivotItem2 -> PageB -> PageC
PivotItem3 -> PageD -> PageE - PageF (Pressing Back Button on PageF will use NonLinear Navigation Service back to Main page)
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.
I'm using MVVM Light and NonLinear Navigation Service if that helps or hurts what I'm trying to accomplish.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
@Tyler,Cyberherbalist:我很遗憾我不能直接在您的讨论中“添加评论”。我的声誉还是太低了。我没有任何博客可以将其发布在那里并为您提供指向它的链接。我就写在这里,因为我认为值得注意并写在某个地方,所以其他人也可以检查/使用/性能从中获利。
..所以,请原谅我在这里写这篇“题外话”:)
虽然我不知道如何很好地解决问题 - 我的解决方案通常是手动收集导航历史记录堆栈,将其放入 iso,并在激活时恢复然后跳到右边/最后一个地方 - 我可以告诉你一些关于墓碑的事情。
问题是,如果您的应用程序被停用,并不意味着它已被逻辑删除。停用只是意味着您的应用程序被移出了屏幕。在 Mango 版本中,您可以点击并按住“后退”设备按钮,查看当前打开的应用程序,然后跳转到任何应用程序。 “激活”是指您的应用程序被唤醒。即使在 WP7 SDK+模拟器的早期版本中,我也从我的应用程序中调用外部媒体播放器,并且我的应用程序几乎从未被物理杀死。停用/激活总是在“暂停”的地方恢复我的应用程序。所有内存中的对象都未受影响。
当设备资源不足时,就会发生逻辑删除,并且必须“终止”一些后台任务以释放内存。我相信当设备的屏保下拉或者设备长时间处于待机状态时也可能会出现这种情况。逻辑删除实际上会杀死您的应用程序,所有内存中的对象都将被销毁/删除等等。唯一能够幸存的就是 AppSettings 和 ISO 存储。 仅当您的应用程序处于停用状态时,墓碑才会发生。
那么,您可以看到哪些生命周期?
1)“冻结/待机/失焦”:
2)“墓碑”:
这意味着,墓碑可能有点难以检测,但也意味着,您总是有时间尝试在停用事件处理程序中保持相同的状态。
这也意味着(除非有一些我还不知道的通知服务),检测从墓碑恢复是否依赖的唯一方法是依赖最致命/最不愉快的效果其中:关于清除你的记忆。
想象一个最简单的情况:您的 App 对象有一个属性“private bool _tomb_test”。它可以是任何类型的任何属性/字段。您也可以使用“object ViewModel{get;set}”来实现此目的。
首先要记住的是,不在构造函数中设置它,并且不分配内联默认值。让它漂浮即可。每当新创建 App 对象时,编译器/运行时都会将其设置为默认 false。这就是重点!
现在:
虽然它看起来很漂亮,但请原谅我的冗长免责声明:
我在当前应用程序中成功使用了它,并且 100% 成功,但我不能说这是有保证的平台行为。我还没有时间在 MSDN 上挖掘事实。以上所有内容均来自我对 7.0 和 7.1 SDK 版本的观察。
上述方法的一个小问题是,它依赖(未经证实?)的假设,即内存清除以“全有或全无”的方式进行。
也就是说,假设所有对象都被清除,或者没有发生清除(当前事实:App 对象被观察到从头开始重新创建,甚至发生初始导航来重新创建 UI。在其他情况下,这两种情况都不会发生)发生)。
对于错误的假设...我无法想象谁以及为什么会决定在.net 世界中实施部分内存清除。完全清除意味着杀死该应用程序。部分清除意味着销毁 GC 代中的随机活动对象,并让所有剩余的对象保持悬空句柄或空句柄。我无法想象。我没有观察到。因此,我认为这是全有或全无的情况。
顺便提一句。如果您观察到部分清除并找到了导致它的主要确定性方式,以便其他人也可能看到它,请大声广播! :)
@Tyler, Cyberherbalist: I regret I cannot just 'add a comment' to your discussion right there. 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.
..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.
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. "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. 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. 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. The only thing that will survive is the AppSettings and the ISO store. Tombstoning is guaranteed to happen ONLY if your application is in deactivated state.
So, what life-cycles you can see?
1) "Freeze/Standby/Unfocus":
2) "Tombstoned":
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.
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.
Imagine a simpliest case: your App object has a property "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.
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. And that's the point!
now:
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. I have yet to find time to dig for the facts on MSDN. All of the above cames from my observations on the 7.0 and 7.1 SDK releases.
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.
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).
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. 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. 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! :)
我有一个类似的导航应用程序,它可以满足您的需求(也使用非线性导航服务)。在我的例子中,我将用户的当前页面/枢轴项目存储在独立存储中,以及指示应用程序是否从逻辑删除返回的令牌(或布尔值)。当用户导航到页面时,页面加载会在 iso 中设置当前页面值,如果页面有枢轴,它还会将当前枢轴设置为第一个。 hub_changed 事件包含将新的当前数据透视表更改为用户刚刚更改的数据透视表的代码。
当应用程序处于逻辑删除过程中时,会触发 app_deactivate 事件,在这里我将 iso 中的 IsTombstoned 值设置为 true。
当用户从逻辑删除返回时,主 page_load 首先检查应用程序是否从逻辑删除状态重新激活 (IsTombstoned=true),如果是,它会立即导航到名称存储在 iso 中的页面。当当前的 page_load 触发时,它会检查 IsTombstoned=true 是否为 true,如果是,则将其设置为 false(恢复正常),如果页面上有数据透视表,则将选定的数据透视表项设置为存储的当前数据透视表。如果页面没有枢轴控件,则当前枢轴将留空。如果页面被逻辑删除时存在动态内容,您还需要提供其恢复。
抱歉,我没有向您展示代码,但我远离工作站,无法访问它。
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. The pivot_changed event has code to change the new current pivot to one the user just changed to.
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.
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. 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. If the page doesn't have a pivot control, the current pivot is left blank. 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.