我有一个垃圾收集问题(我认为)。
让我解释:
这是我的活动的简化版本:
public Fragment fragA;
public Fragment fragB;
private FragmentManager manager = getSupportFragmentManager();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
if (savedInstanceState == null) {
fragA = new FragA();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.container, fragA);
transaction.commit();
}
}
//A USER CLICK ON A BUTTON (in fragment A) TO SHOW FRAGMENT B:
public void showFragB() {
fragB = new FragB();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.container, fragA);
transaction.commit();
}
//A USER CLICK ON A BUTTON (in fragment B) TO DO SOME ACTIONS THAT REQUIRE fragA:
public void doSomethingWithFragA() {
if (fragA == null)
Log.d("TAG", "WTF HAPPENS!?"
else
Log.d("TAG", "great, we can do the action"
}
现在,大多数情况下,此功能正常。
问题是...如果我打开应用程序,按按钮(在片段A中)以显示片段B,按家庭按钮(并执行需要ram等操作,例如浏览或观看youtube视频),返回我的应用程序,按其他按钮(在片段B中)... fragA为空!!!
但是该应用程序并未完全重新创建,因为当我返回它时,片段B是可见的,就像该应用程序永远不会自行关闭一样。
所以...您能解释一下这种现象以及如何解决吗?
非常感谢!
最佳答案
但是该应用程序并未完全重新创建,因为当我返回到该应用程序时,
片段B是可见的,就像该应用程序永远不会自行关闭一样。
那是错误的。您的应用程序可能会被完全重新创建,但是fragB
会被系统重新加载,因为它在按下主页按钮(在本例中为R.id.container)时已附加到容器上。
在所描述的场景中,savedInstanceState
不为null,因此您的代码将不会创建fragA
。重要的是要注意,只有附加的片段会自动重新创建,但是您用替换替换了fragA
,因此系统也不会重新创建它。 (替换将分离附加到该容器的每个片段,然后附加新片段。)
有几个解决此问题的方法,但是我认为最优雅的方法是将fragA
设置为目标片段:
public void showFragB() {
fragB = new FragB();
// this line will force the system to recreate fragA,
// if fragB is recreated;
fragB.setTargetFragment(fragA, 0);
FragmentTransaction transaction = manager.beginTransaction();
// I assumed fragA here is just a typo (it should be fragB)
transaction.replace(R.id.container, fragA);
transaction.commit();
}
然后,您可以在
getTargetFragment
中使用fragB
来引用fragA
。重要:
您意识到
fragA
为null,但实际上fragB
也为null,因此您从未在代码中使用该引用。原因是系统只是为您重新创建了片段,但正式地,这不会使您的
fragA
,fragB
等……引用指向实际重新创建的片段(如果片段可见,也不会)。您必须手动执行此操作:if (savedInstanceState == null) {
fragA = new FragA();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.container, fragA, "TAG_TO_FIND_FRAG_A");
transaction.commit();
}
else{
fragA = manager.findFragmentByTag("TAG_TO_FIND_FRAG_A");
if(fragA == null){
// fragA was not attached so the system have not reacreted it
} else {
// fragA was attached!
}
}
笔记:
fragB
的引用应该像上面的fragA
一样进行设置。在这种情况下,可以轮换重现问题。它是
容易得多。
阅读整个doc片段!
关于java - fragment 和垃圾收集器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24720722/