Android:防止片段在替换另一个片段时变成"active"
Android: Prevent fragment from becoming "active" while replacing another
我有以下调用:
context.getSupportFragmentManager().popBackStack(tag.name(), 1);
context.getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, fragment, tag.name()).addToBackStack(tag.name()).commit();
...而我之前打开的后台堆栈上至少有 2 个其他片段。当执行这两个命令并且最新的片段已从后台堆栈中弹出时,在很短的时间内,在弹出的片段被给定片段替换之前,该片段之前的片段将处于活动状态。这就是问题所在,因为此片段从服务器获取数据并显示进度对话框。有时这会导致竞争条件和奇怪的行为。
如何防止 "non-active" 片段在替换另一个片段时变为活动状态?
这里是对这种情况的简短解释:
MainActivity -> 打开 Fragment1 -> 打开 Fragment2a -> 打开 EditActivity -> 在 "save action" 之后,Fragment2a 将被弹出,并在 MainActivity 的 fragment_container 中添加一个新的 Fragment2b。虽然发生这种情况,但 Fragment1 正在做一些事情,但它不能这样做。我想阻止 Fragment1 执行任何任务。它应该以某种方式留在后台并且 "sleep".
检查
if(getActivity() == null || !isAdded){
return; //don't do your code that touches UI if it is not active.
}
但是如果您不打算等待完成,请确保您的 onPause 删除了您的忙碌指示器,否则您将造成 window 内存泄漏。
使用观察者模式怎么样?您创建一个接口,该接口具有将片段设置为繁忙启动或执行某些逻辑的方法。
所有片段都实现了这个接口,你创建了一个包含这些接口的列表 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。
我不确定我是不是误用了片段管理器的概念导致了这种情况的发生,或者片段管理器的概念是否完全是废话(就像 Android 中的很多),但我解决了这个问题使用一些解决方法。当我开始或替换一个新片段时,我会立即在应用程序上下文中存储一个 ID。当片段开始时,它会检查它是否具有正确的 ID。如果不是,我 return 一个空视图并且不会创建片段。支票如下所示:
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
{
return FragmentCreationHelper.createFragmentView(inflater, container, TAG, getFragmentId(), R.layout.fragment_mycoolview);
}
帮手class...
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;
}
}
}
我有以下调用:
context.getSupportFragmentManager().popBackStack(tag.name(), 1);
context.getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, fragment, tag.name()).addToBackStack(tag.name()).commit();
...而我之前打开的后台堆栈上至少有 2 个其他片段。当执行这两个命令并且最新的片段已从后台堆栈中弹出时,在很短的时间内,在弹出的片段被给定片段替换之前,该片段之前的片段将处于活动状态。这就是问题所在,因为此片段从服务器获取数据并显示进度对话框。有时这会导致竞争条件和奇怪的行为。
如何防止 "non-active" 片段在替换另一个片段时变为活动状态?
这里是对这种情况的简短解释: MainActivity -> 打开 Fragment1 -> 打开 Fragment2a -> 打开 EditActivity -> 在 "save action" 之后,Fragment2a 将被弹出,并在 MainActivity 的 fragment_container 中添加一个新的 Fragment2b。虽然发生这种情况,但 Fragment1 正在做一些事情,但它不能这样做。我想阻止 Fragment1 执行任何任务。它应该以某种方式留在后台并且 "sleep".
检查
if(getActivity() == null || !isAdded){
return; //don't do your code that touches UI if it is not active.
}
但是如果您不打算等待完成,请确保您的 onPause 删除了您的忙碌指示器,否则您将造成 window 内存泄漏。
使用观察者模式怎么样?您创建一个接口,该接口具有将片段设置为繁忙启动或执行某些逻辑的方法。
所有片段都实现了这个接口,你创建了一个包含这些接口的列表 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。
我不确定我是不是误用了片段管理器的概念导致了这种情况的发生,或者片段管理器的概念是否完全是废话(就像 Android 中的很多),但我解决了这个问题使用一些解决方法。当我开始或替换一个新片段时,我会立即在应用程序上下文中存储一个 ID。当片段开始时,它会检查它是否具有正确的 ID。如果不是,我 return 一个空视图并且不会创建片段。支票如下所示:
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
{
return FragmentCreationHelper.createFragmentView(inflater, container, TAG, getFragmentId(), R.layout.fragment_mycoolview);
}
帮手class...
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;
}
}
}