Android:防止片段成为"活跃"而替换另一个

时间:2017-09-21 19:58:29

标签: android android-fragments fragmentmanager

我有以下调用:

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执行任何任务。它应该以某种方式留在背景中并且睡眠"。

3 个答案:

答案 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;
        }
    }
}