如何正确地删除保留的实例片段 [英] How to properly remove retained instance Fragment
问题描述
目前,我想保留一个昂贵的数据结构,在配置更改。我选择不使用捆绑
来处理它,因为昂贵的数据结构不parcelable。
因此,我使用了非UI片段(称之为 RetainInstanceFragment ),其 setRetainInstance(真)
来保存数据结构。
公共类RetainInstanceFragment扩展片段{
@覆盖
公共无效的onCreate(捆绑savedInstanceState){
super.onCreate(savedInstanceState); //创建昂贵的数据结构
expensiveDataStructure = CreateExpensiveDataStructure(); //告诉框架,尽量保持这个片段各地
//配置更改时。
setRetainInstance(真);
} 公共ExpensiveDataStructure expensiveDataStructure = NULL;
}
这是UI片段(称之为 UIFragment )将获得 RetainInstanceFragment
昂贵的数据结构。每当有上配置更改 UIFragment
, UIFragment
将始终尝试让缓存 RetainInstanceFragment
从 FragmentManager
,才决定创建一个新的 RetainInstanceFragment
。
例子code是如下。
公共类UIFragment扩展SherlockListFragment
@覆盖
公共无效onActivityCreated(捆绑savedInstanceState){
super.onActivityCreated(savedInstanceState); FragmentManager FM = getFragmentManager(); //检查是否我们保留了工人的片段。
retainInstanceFragment =(RetainInstanceFragment)fm.findFragmentByTag(数据); //如果不保留(或第一次运行),我们需要创建它。
如果(retainInstanceFragment == NULL){
retainInstanceFragment =新RetainInstanceFragment();
fm.beginTransaction()加(watchlistArrayFragment,数据)提交()。
}其他{
//我们可以重新使用retainInstanceFragment.expensiveDataStructure甚至
//配置更改后。
}
}
}
不过,有一个问题。每当我毁掉我的老 UIFragment
,并用新的替换 UIFragment
,我希望老 RetainInstanceFragment
也将被销毁。这是我如何毁灭和创造新的 UIFragment
公共类MyFragmentActivity扩展SlidingFragmentActivity
当在滑动菜单是不同的菜单项//被触发
//选择。
公共无效selectActiveContent(国家国家){
片段片段=新UIFragment(国家);
。getSupportFragmentManager()调用BeginTransaction()取代(R.id.content,片段).commitAllowingStateLoss()。
}
但是老 RetainInstanceFragment
永远不会被破坏。
我的猜测是,也许我忘了要执行清理 UIFragment
。因此,我添加以下code
UIFragment
@覆盖
公共无效onDetach(){
super.onDetach();
//为了区分这是否是一个配置的变化,或者我们是
//删除不掉了片段?
如果(this.isRemoving()){
FragmentManager FM = getFragmentManager();
。fm.beginTransaction()删除(retainInstanceFragment).commit();
}
}
但是,它不工作的所有时间。我执行几个滑动菜单点击。
1。 selectActiveContent() - >创建新UIFragment和新RetainInstanceFragment
2. selectActiveContent() - >创建新UIFragment,而是重新使用previous RetainInstanceFragment。 (错误的行为)
3. selectActiveContent() - >创建新UIFragment和新RetainInstanceFragment。
4. selectActiveContent() - >创建新UIFragment,而是重新使用previous RetainInstanceFragment。 (错误的行为)
任何想法如何,我可以正常删除保留实例片段?
作为建议的@Luksprog,下面的方法效果。 但是,它仍然没有解释为什么通过 onDetach
做了previous清理不起作用。如果任何人都可以解释为什么这个解决方案工程和previous不,我会非常感激。 :)
UIFragment
@覆盖
公共无效onDetach(){
super.onDetach();
}公共无效cleanu pretainInstanceFragment(){
FragmentManager FM = getFragmentManager();
。fm.beginTransaction()删除(this.retainInstanceFragment).commit();
}
MyFragmentActivity
公共类MyFragmentActivity扩展SlidingFragmentActivity
当在滑动菜单是不同的菜单项//被触发
//选择。
公共无效selectActiveContent(国家国家){ // *********
//解决方案通过@Luksprog建议。有用!
//但是我不知道为什么它的工作原理和previous没有工作...
// *********
片段oldFragment = getSupportFragmentManager()findFragmentById(R.id.content)。
如果(oldFragment的instanceof UIFragment){
((UIFragment)oldFragment).cleanu pretainInstanceFragment();
} 片段片段=新UIFragment(国家);
。getSupportFragmentManager()调用BeginTransaction()取代(R.id.content,片段).commitAllowingStateLoss()。
}
(编辑)由@Luksprog有用的注释
片段交易不发的时候了。我的假设是
,在onDetach()回调这样做,交易将不会删除
在保留片段实例之前的UI片段的替换
交易完成,因此新的UI片段仍然会看到
保留片段的实例仍然可用,所以它不会创建一个新的
一。您的previous方法不在片段的精神
框架,碎片不知道其他的片段和的
活动管理所有这些,因为它知道更多关于整体
应用程序的状态。
块引用>Currently, I would like to retain an expensive data structure, during configuration changes. I choose not to use
Bundle
to handle it, as the expensive data structure is not parcelable.Hence, I use a non-UI Fragment (Called it RetainInstanceFragment), with its
setRetainInstance(true)
to hold the data structure.public class RetainInstanceFragment extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Creating expensive data structure expensiveDataStructure = CreateExpensiveDataStructure(); // Tell the framework to try to keep this fragment around // during a configuration change. setRetainInstance(true); } public ExpensiveDataStructure expensiveDataStructure = null; }
An UI Fragment (Called it UIFragment) will get the expensive data structure from
RetainInstanceFragment
. Whenever there is configuration changes onUIFragment
,UIFragment
will always try to get the "cached"RetainInstanceFragment
fromFragmentManager
, before it decides to create a newRetainInstanceFragment
.Example code is as follow.
public class UIFragment extends SherlockListFragment @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); FragmentManager fm = getFragmentManager(); // Check to see if we have retained the worker fragment. retainInstanceFragment = (RetainInstanceFragment)fm.findFragmentByTag("data"); // If not retained (or first time running), we need to create it. if (retainInstanceFragment == null) { retainInstanceFragment = new RetainInstanceFragment(); fm.beginTransaction().add(watchlistArrayFragment, "data").commit(); } else { // We can re-use retainInstanceFragment.expensiveDataStructure even // after configuration change. } } }
However, there's a problem. Whenever I destroy my old
UIFragment
, and replace it with newUIFragment
, I expect oldRetainInstanceFragment
will be destroyed as well. Here is how I destroy and create newUIFragment
public class MyFragmentActivity extends SlidingFragmentActivity // Being triggered when there is different menu item in sliding menu being // selected. public void selectActiveContent(Country country) { Fragment fragment = new UIFragment(country); getSupportFragmentManager().beginTransaction().replace(R.id.content, fragment).commitAllowingStateLoss(); }
But old
RetainInstanceFragment
is never destroyed.My guess is, perhaps I forget to perform clean up in
UIFragment
. Hence, I add the following codeUIFragment
@Override public void onDetach() { super.onDetach(); // To differentiate whether this is a configuration changes, or we are // removing away this fragment? if (this.isRemoving()) { FragmentManager fm = getFragmentManager(); fm.beginTransaction().remove(retainInstanceFragment).commit(); } }
However, it doesn't work all the time. I perform several sliding menu clicks.
1. selectActiveContent() -> Create new UIFragment and new RetainInstanceFragment 2. selectActiveContent() -> Create new UIFragment, but re-use previous RetainInstanceFragment. (Wrong behavior) 3. selectActiveContent() -> Create new UIFragment, and new RetainInstanceFragment. 4. selectActiveContent() -> Create new UIFragment, but re-use previous RetainInstanceFragment. (Wrong behavior)
Any idea how I can properly remove retained instance Fragment?
解决方案As suggested by @Luksprog, the following method works. However, it still do not explain why the previous cleanup done through
onDetach
doesn't work. If anyone can explain why this solution works and previous doesn't, I would be very thankful. :)UIFragment
@Override public void onDetach() { super.onDetach(); } public void cleanupRetainInstanceFragment() { FragmentManager fm = getFragmentManager(); fm.beginTransaction().remove(this.retainInstanceFragment).commit(); }
MyFragmentActivity
public class MyFragmentActivity extends SlidingFragmentActivity // Being triggered when there is different menu item in sliding menu being // selected. public void selectActiveContent(Country country) { // ******************************************* // Solution suggested by @Luksprog. It works! // But I have no idea why it works and previous doesn't work... // ******************************************* Fragment oldFragment = getSupportFragmentManager().findFragmentById(R.id.content); if (oldFragment instanceof UIFragment) { ((UIFragment)oldFragment).cleanupRetainInstanceFragment(); } Fragment fragment = new UIFragment(country); getSupportFragmentManager().beginTransaction().replace(R.id.content, fragment).commitAllowingStateLoss(); }
(Edited) Useful comment by @Luksprog
The fragment transactions are not made right away. My assumption was that doing that transaction in the onDetach() callback will not remove the retain fragment instance before the UI fragment's replace transaction finished and so your new UI fragment will still see the retain fragment instance still available, so it will not create a new one. Your previous method is not in the spirit of the fragments framework where fragments are unaware of other fragments and the activity manages all of them as it knows more about the overall application state.
这篇关于如何正确地删除保留的实例片段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!