gpt4 book ai didi

android - 如何正确删除保留的实例 fragment

转载 作者:塔克拉玛干 更新时间:2023-11-02 18:51:04 26 4
gpt4 key购买 nike

目前,我想在配置更改期间保留一个昂贵的数据结构。我选择不使用 Bundle 来处理它,因为昂贵的数据结构不可分割。

因此,我使用一个非 UI fragment (称为 RetainInstanceFragment)及其 setRetainInstance(true) 来保存数据结构。

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

UI fragment (称为 UIFragment)将从 RetainInstanceFragment 获取昂贵的数据结构。每当 UIFragment 的配置发生变化时,UIFragment 将始终尝试从 FragmentManager 获取“缓存的”RetainInstanceFragment,在它决定创建一个新的 RetainInstanceFragment 之前。

示例代码如下。

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.
}
}
}

但是,有一个问题。每当我销毁旧的 UIFragment,并用新的 UIFragment 替换它时,我预计旧的 RetainInstanceFragment 也会被销毁。 以下是我如何销毁和创建新的 UIFragment

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();
}

但是旧的 RetainInstanceFragment 永远不会被销毁。

我的猜测是,也许我忘记了在 UIFragment 中执行清理。因此,我添加了以下代码

UI fragment

@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();
}
}

然而,它并不是一直有效。我执行了几次滑动菜单点击。

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)

知道如何正确删除保留的实例 fragment 吗?

最佳答案

正如@Luksprog 所建议的,以下方法有效。 但是,它仍然没有解释为什么之前通过 onDetach 完成的清理不起作用。如果有人能解释为什么这个解决方案有效而以前的没有,我会非常感谢。 :)

UI fragment

@Override
public void onDetach() {
super.onDetach();
}

public void cleanupRetainInstanceFragment() {
FragmentManager fm = getFragmentManager();
fm.beginTransaction().remove(this.retainInstanceFragment).commit();
}

我的 fragment Activity

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();
}

(已编辑)@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.

关于android - 如何正确删除保留的实例 fragment ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15565408/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com