在 show() 之前获取 DialogFragment 子类中的父活动
Posted
技术标签:
【中文标题】在 show() 之前获取 DialogFragment 子类中的父活动【英文标题】:Get parent activity in DialogFragment subclass before show() 【发布时间】:2019-01-17 07:57:29 【问题描述】:我正在开发一个带有许多对话框的 android 应用程序,所有这些对话框都扩展了一个名为“DialogFragmentBase”的自定义类,该类扩展了库的“DialogFragment”。所有活动都使用在 DialogFragmentBase 中重写的 show() 方法。
如果父活动是后台的(如接听电话),我想阻止显示对话框,因为这会导致非法状态异常,但同时我不想保护每个 show() 调用应用程序:
if(getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED))
所以我想在 DialogFragmentBase 中做这样的事情:
@Override
public void show(FragmentManager manager, String tag)
List<Fragment> fragments = manager.getFragments();
if(fragments != null && fragments.size() > 0)
FragmentActivity activity = fragments.get(fragments.size()-1).getActivity();
if(activity != null && activity.getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED))
super.show(manager, tag);
所以我的问题是:像这样访问上一个片段是否被认为是一种不好的做法?它确实有效......但我记得在某个地方读到片段不应该相互交流。如果这确实是一种不好的做法,那么可以在 DialogFragmentBase 中实现的更好的解决方案是什么(以避免在任何地方添加警卫)。
注意:我尝试了here 中描述的 onSaveInstanceState 解决方案,但由于尚未显示 DialogFragment,因此此时不需要调用 onSaveInstanceState。 getActivity() 也返回 null,因为此时尚未调用 onAttach。
谢谢!
【问题讨论】:
【参考方案1】:support library FragmentManager
有一个isStateSaved()
method。根据您的具体要求,您可以利用它来检查显示对话框是否“安全”:
@Override
public void show(FragmentManager manager, String tag)
if (!manager.isStateSaved())
super.show(manager, tag);
请注意,上面的实现与使用commitAllowingStateLoss()
比较相似,因为在某些情况下您会默默地无法显示您的对话框。但也许这符合您的要求。
【讨论】:
isStateSaved() 会返回 false,即使父活动已经在后台。我开始认为commitAllowingStateLoss()
可能不是一个糟糕的方法(至少在我的情况下,因为如果应用程序在后台,我想向用户显示的对话框是无用的)。
一般来说,如果父activity在后台但是状态还没有被保存,那是显示对话框的好时机。当用户返回应用程序时,对话框将可见。
真的吗?这不是我所看到的,我得到的是illegalStateException
可能是因为我使用的是show()
而不是commitNow()
,所以到节目安排的时候,状态已经被保存了?
假设你得到的异常是can not be performed after onSaveInstanceState()
一个,那么是的。重要的是片段管理器是否保存了它的状态;如果没有,那么任何交易都是安全的。但你是对的,我相信在某些情况下可以将事务添加到队列中,然后让片段管理器在处理该事务之前保存其状态。
所以我设法让它通过这样做: if(!manager.isStateSaved() && !savedInstanceStateDone) transaction.commitNow(); 这看起来好吗?【参考方案2】:
也许您可以在对话框基类中创建一个新方法:
public void showIfResumed(FragmentActivity activity, String tag)
if (/* your check here, e.g. activity.getLifecycle()... */)
show(activity.getSupportFragmentManager(), tag);
然后,在您的活动中,您可以调用showIfResumed(this, TAG)
,而不是调用show(getSupportFragmentManager(), TAG)
。您仍然需要将每次调用 show()
更改为调用 showIfResumed()
,但这会大大减少代码重复。
【讨论】:
谢谢这是我的下一个选择,但访问片段列表的解决方案是一种不好的做法吗?因为它允许我不更改 DialogFragmentBase 中的任何内容。虽然使用您的解决方案,但我必须进行很多更改,我希望有一个可以轻松实施的解决方案,而不是依赖开发人员调用不直观的 showIfResumed。 @MennaMostafa 我会说是的,您在问题中发布的内容是一种不好的做法。为什么您的片段向片段管理器询问正在管理的其他片段?如果没有“前一个”片段会发生什么?如果“前一个”片段未附加到活动会发生什么?等等。您可能会更改基类中现有的show()
方法以抛出UnsupportedOperationException
,这样任何使用它的人都会立即看到他们不应该这样做。以上是关于在 show() 之前获取 DialogFragment 子类中的父活动的主要内容,如果未能解决你的问题,请参考以下文章