从 onContextItemSelected 显示的 DialogFragment 无法在 onPause/onResume 中继续存在
Posted
技术标签:
【中文标题】从 onContextItemSelected 显示的 DialogFragment 无法在 onPause/onResume 中继续存在【英文标题】:DialogFragment displayed from onContextItemSelected doesn't survive onPause/onResume 【发布时间】:2012-12-10 13:30:27 【问题描述】:我有一个 DialogDragment,我可以显示以下两种方式之一:
1) 通过从其 OnItemClickListener 中点击 ListView 项目
2) 通过激活 ListView 的上下文菜单并选择一个菜单项
执行 #1 在所有生命周期事件下都可以正常工作,但如果我通过 #2 调用它并暂停活动(通过返回 Home)并通过任务切换器恢复它,则不再显示对话框。片段就在那里,我可以旋转设备并显示对话框。
我进行了实验,如果我将 DialogFragment 的显示放入一个延迟至少 1/2 秒的 Handler 中,它可以工作。
以下 sn-p 失败 -- 它显示对话框,但随后暂停/恢复将其隐藏:
public boolean onContextItemSelected(android.view.MenuItem item)
boolean consumed = false;
switch (item.getItemId())
case R.id.menu_item:
showMyDialogFragment();
consumed = true;
break;
return consumed;
所以下面的 sn-p 工作。暂停/继续正确显示对话框:
public boolean onContextItemSelected(android.view.MenuItem item)
boolean consumed = false;
switch (item.getItemId())
case R.id.menu_item:
new Handler().postDelayed(new Runnable()
public void run()
showMyDialogFragment();
, 300);
consumed = true;
break;
return consumed;
用 0 毫秒或 250 毫秒的延迟代替 300 毫秒的延迟会导致它再次被破坏。这种可重复性 100% 的时间。
这显然是一个可怕的 hack,可能取决于设备速度的常数使情况变得更糟。
有人知道为什么会这样和/或提供更好的解决方案吗?我在这个问题上花了几个小时,这是我能想到的最好的。
【问题讨论】:
我认为这可能与菜单隐藏动画有关。即使是旧的、速度较慢的 Nexus One,300 毫秒的延迟也有效。 如果有机会,请发布一个完整的示例项目来演示这种现象,因为我想看看它。如果它真的是一个平台错误,我们无论如何都需要那个项目来帮助解决问题。此外,这是使用原生 API 级别 11 片段,还是 Android 支持包的反向移植?如果是后者,您确定您使用的是最新版本的 Android Support JAR? 这里是演示问题的示例项目:github.com/androidmoney/Menu-DialogFragment-Test 它发生在本机和支持片段包上。要显示问题,请显示对话框按钮或菜单项。然后暂停(转到主页)并继续(使用应用切换器重新进入应用)。 我遇到了一个非常相似(相同?)的问题:***.com/questions/18730141/… 【参考方案1】:我可以在 Android 4.2(ARM 模拟器和 Galaxy Nexus)上重现这一点。我无法在 x86 4.1 模拟器、Nexus S (4.1) 和 Motorola RAZR i (4.0) 上重现您的发现。我还可以通过修改我自己的一本图书样本来重现该问题。我使用您的示例提交了一个问题:http://code.google.com/p/android/issues/detail?id=41901 请添加您认为有助于他们诊断问题的任何其他信息。
关于解决方法,如果 300 毫秒有效,那么我们遇到了其中一个可爱的“时间问题”,我不知道你会如何解决它,除非不使用菜单来显示它.例如,对于您的示例应用程序,只需切换到SHOW_AS_ACTION_ALWAYS
(因此让它成为操作栏上的一个项目,而不是在溢出菜单中)就足以让DialogFragment
正常运行。希望您有办法调整您的 UI 以弥补这个错误,或者也许有人会想出另一种解决方法并将其发布在此处或问题上。
【讨论】:
谢谢。对我来说,重新设计我的应用程序是不可能的,因为我非常依赖上下文和操作栏溢出菜单中的对话框。【参考方案2】:我建议在所有暂停时销毁对话框,并根据状态在 onResume 中重新创建,而不管对话框是如何被调用的。如果应用程序在暂停时被操作系统杀死,否则会存在内存泄漏的风险。
要明确回答您的问题,请不要依赖操作系统来维护您的应用状态。
【讨论】:
操作系统保持对话状态很好,期待可见性方面。如果我之后旋转屏幕,对话框会再次显示。我刚刚在 JB 4.2 的 People 应用程序中测试了同样的事情,同样的事情发生了。该对话框在 onPause/onRestore 时消失。这显然是一个 Android 错误。 确实很可能是一个Android错误。我的想法是,您不应该依赖操作系统为您维护状态,因为这样的“错误”可能会出现在不同版本的操作系统中。如果您想期待某个结果,请做一些小事,例如跟踪您自己的状态。许多意想不到的事情可能会突然出现。这只是很好的编程。 好的,谢谢。这可能是一个很好的建议,尽管有点破坏了使用 Fragments 的优势之一。 并非如此。片段旨在成为可重用的可视界面定义。在这种情况下,我们正在处理一个对话框,它使用片段作为其视觉定义,但这与维护视觉状态是分开的——无论对话框是否显示。以上是关于从 onContextItemSelected 显示的 DialogFragment 无法在 onPause/onResume 中继续存在的主要内容,如果未能解决你的问题,请参考以下文章