为什么我必须 "invalidate" 我的 window 才能避免碎片消失?
Why do I have to "invalidate" my window to avoid disappearing fragments?
我有一个功能齐全的应用程序,其中三个选项卡在三个片段之间切换。然后我对后端做了一些相当大的改变,但我认为没有什么会干扰 GUI。但它确实发生了——碎片现在往往会消失。
选项卡更改如下:
mActiveFragment = null;
switch (index) {
case 0:
mActiveFragment = new TabOneFragment();
getSupportActionBar().setSubtitle("One");
break;
case 1:
mActiveFragment = new TabTwoFragment();
getSupportActionBar().setSubtitle("Two");
break;
case 2:
mActiveFragment = new TabThreeFragment();
getSupportActionBar().setSubtitle("Three");
break;
}
getSupportFragmentManager().beginTransaction().replace(R.id.pnlTabContent, mActiveFragment).commit();
在我进行看似无关的更改之前,这工作得很好。现在,它工作了几次,然后片段容器保持为空,直到我关闭并重新打开 activity。
- 当片段消失时,我的操作栏中最右边的按钮也消失了,而且操作栏按钮似乎都不起作用。
- 它的工作次数似乎是随机的(但很少,通常是两到三个选项卡更改)。
- 没有抛出任何异常,我在 logcat 中看不到任何有趣的东西(只有来自我的应用程序的常规日志消息)。
- fragments永远不会为null,并执行它们的onActivityCreated、onCreateView和onAttach方法。
- 片段容器 (pnlTabContent) 永远不会消失(我将背景颜色更改为红色,以验证)。
- 片段中的视图 returns isShown 为真,这应该表明没有父视图的可见性设置为 GONE 或 INVISIBLE。无论如何,我检查了整个代码库,没有发现任何代码改变父容器的可见性。
- 他们只是没有出现。
现在,我发现如果我在标签更改后添加此行,标签更改总是有效:
getWindow().addFlags(WindowManager.LayoutParams.LAYOUT_CHANGED);
或与此相关的任何其他标志。所以看来我现在需要刷新 window 以防止碎片消失。
关于为什么会发生这种情况有什么想法吗?我知道在没有看到我所做的更改的情况下很难调试,但由于它们非常大,并且分布在 20 多个不同的文件中,我认为共享它们没有任何意义。所以我正在寻找可能出错的一般想法。
嗯,当然,在处理这个问题五个小时后,我在此处发布问题后立即解决了它。
事实证明,我的其中一项更改是错误修复,用于修复在我的一个 ArrayAdapter 上调用 notifyDataSetChanged
时的 CalledFromWrongThreadException
。由于此 class 无法访问任何 Activity,我在 UI 线程上使用了一个处理程序来 运行 它:
Handler mainHandler = new Handler(context.getMainLooper());
Runnable myRunnable = new Runnable() {
@Override
public void run() {
adapter.notifyDataSetChanged();
}
};
mainHandler.post(myRunnable);
出于某种原因,这对我的 activity 造成了影响。我不太了解处理程序,但我想我造成了某种不一致。我更改了代码,运行 它来自实际的 activity 的 运行OnUIThread(),现在一切都恢复正常了。
我有一个功能齐全的应用程序,其中三个选项卡在三个片段之间切换。然后我对后端做了一些相当大的改变,但我认为没有什么会干扰 GUI。但它确实发生了——碎片现在往往会消失。
选项卡更改如下:
mActiveFragment = null;
switch (index) {
case 0:
mActiveFragment = new TabOneFragment();
getSupportActionBar().setSubtitle("One");
break;
case 1:
mActiveFragment = new TabTwoFragment();
getSupportActionBar().setSubtitle("Two");
break;
case 2:
mActiveFragment = new TabThreeFragment();
getSupportActionBar().setSubtitle("Three");
break;
}
getSupportFragmentManager().beginTransaction().replace(R.id.pnlTabContent, mActiveFragment).commit();
在我进行看似无关的更改之前,这工作得很好。现在,它工作了几次,然后片段容器保持为空,直到我关闭并重新打开 activity。
- 当片段消失时,我的操作栏中最右边的按钮也消失了,而且操作栏按钮似乎都不起作用。
- 它的工作次数似乎是随机的(但很少,通常是两到三个选项卡更改)。
- 没有抛出任何异常,我在 logcat 中看不到任何有趣的东西(只有来自我的应用程序的常规日志消息)。
- fragments永远不会为null,并执行它们的onActivityCreated、onCreateView和onAttach方法。
- 片段容器 (pnlTabContent) 永远不会消失(我将背景颜色更改为红色,以验证)。
- 片段中的视图 returns isShown 为真,这应该表明没有父视图的可见性设置为 GONE 或 INVISIBLE。无论如何,我检查了整个代码库,没有发现任何代码改变父容器的可见性。
- 他们只是没有出现。
现在,我发现如果我在标签更改后添加此行,标签更改总是有效:
getWindow().addFlags(WindowManager.LayoutParams.LAYOUT_CHANGED);
或与此相关的任何其他标志。所以看来我现在需要刷新 window 以防止碎片消失。
关于为什么会发生这种情况有什么想法吗?我知道在没有看到我所做的更改的情况下很难调试,但由于它们非常大,并且分布在 20 多个不同的文件中,我认为共享它们没有任何意义。所以我正在寻找可能出错的一般想法。
嗯,当然,在处理这个问题五个小时后,我在此处发布问题后立即解决了它。
事实证明,我的其中一项更改是错误修复,用于修复在我的一个 ArrayAdapter 上调用 notifyDataSetChanged
时的 CalledFromWrongThreadException
。由于此 class 无法访问任何 Activity,我在 UI 线程上使用了一个处理程序来 运行 它:
Handler mainHandler = new Handler(context.getMainLooper());
Runnable myRunnable = new Runnable() {
@Override
public void run() {
adapter.notifyDataSetChanged();
}
};
mainHandler.post(myRunnable);
出于某种原因,这对我的 activity 造成了影响。我不太了解处理程序,但我想我造成了某种不一致。我更改了代码,运行 它来自实际的 activity 的 运行OnUIThread(),现在一切都恢复正常了。