我有以下调用:
context.getSupportFragmentManager().popBackStack(tag.name(), 1);
context.getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, fragment, tag.name()).addToBackStack(tag.name()).commit();
...虽然我在后台打开了至少2个其他片段。当这两个命令被执行并且最后一个片段从backstack弹出时,在很短的时间内,该片段之前的片段将在弹出片段被给定片段替换之前处于活动状态。这就是问题所在,因为这个片段从服务器获取数据并显示进度对话框。有时这会导致竞争条件和奇怪的行为。
如何防止"非活跃"替换另一个片段时片段变得活跃?
以下是对情况的简短说明: MainActivity - >打开Fragment1 - >打开Fragment2a - >打开EditActivity - >在"保存动作"之后,将弹出Fragment2a并将新的Fragment2b添加到MainActivity的fragment_container中。当发生这种情况时,Fragment1正在做的事情,但它不能这样做。我想阻止Fragment1执行任何任务。它应该以某种方式留在背景中并且睡眠"。
答案 0 :(得分:1)
使用观察者模式怎么样?您可以创建一个接口,其中包含将片段设置为busy starte或执行某些逻辑的方法。
所有片段都实现此接口,并在Activity中创建一个包含这些接口的列表。如果注册了片段,请将此片段添加到列表中,或者使用取消注册方法将其删除,例如。
可以调用 (MyActivity)getActivity.register(this);
来注册片段。或者,如果您希望将除此之外的其他片段设置为忙(MyActivity)getActivity.setActive(this)
,则可以调用活动片段中的方法,并且在MyActivity中,您可以将此方法声明为
public void setActive(IStateController fragment) {
for(IStateController f: listOfSubscribers) {
if(f == fragment) {
// This fragment called the method and should active
// other fragments can be set to busy or waiting state
}
}
}
我真的不能说它是否适合你,但是可以通过这种方式完成与片段的互动,而不是彼此了解,或者你可以检查EventBus library。
答案 1 :(得分:0)
请检查
if(getActivity() == null || !isAdded){
return; //don't do your code that touches UI if it is not active.
}
但请确保您的onPause删除忙碌指示符然后如果您不打算等待完成,或者您将创建窗口泄漏的内存泄漏。
答案 2 :(得分:0)
我不确定我是否滥用片段管理器概念以便可能发生这种情况,或者如果片段管理器概念是完全废话(在Android中很多),但我通过使用一些解决方法解决了它。当我启动或替换新片段时,我会立即在应用程序上下文中存储一个ID。当片段开始时,它会检查是否具有正确的ID。如果没有,我返回一个空视图,片段不会被创建。支票如下:
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
{
return FragmentCreationHelper.createFragmentView(inflater, container, TAG, getFragmentId(), R.layout.fragment_mycoolview);
}
助手班......
public class FragmentCreationHelper
{
public static View createFragmentView(LayoutInflater inflater, ViewGroup container, String loggingTag, FragmentTag fragmentId, int template)
{
Log.d(loggingTag, "onCreateView()");
if (MyContext.getNextVisibleFragment() == null || fragmentId.equals(MyContext.getNextVisibleFragment()))
{
Log.d(loggingTag, "inflating view...");
return inflater.inflate(template, container, false);
}
else
{
Log.d(loggingTag, "Skipping view inflation. Fragment should not be displayed.");
return null;
}
}
}