保留的Fragment中的实例变量变为null

jus*_*oob 4 android android-fragments

作为一种替代方案Intent,我FragmentActivity重新创建期间将数据保存在保留的无头中(我保存的对象可能非常大,并且它不符合a的大小限制Intent,我认为这是比序列化更快的方法 -例如,反序列化为JSON).

虽然我的实现有点不同,但我从这篇Google文档中得到了这个想法.

Fragment:

public class DataFragment extends Fragment {

    private Data data;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

    public void setData(Data data) {
        this.data = data;
    }

    public Data getData() {
        return data;
    }
}
Run Code Online (Sandbox Code Playgroud)

FragmentonSaveInstanceState()我的方法中将数据保存到此Activity:

@Override
protected void onSaveInstanceState(Bundle outState) {
    FragmentManager fm = getSupportFragmentManager();
    dataFragment = (DataFragment) fm.findFragmentByTag(TAG_DATA);
    if (dataFragment == null) {
        dataFragment = new DataFragment();
        fm.beginTransaction().add(dataFragment, TAG_DATA).commitNow();
    }
    dataFragment.setData(myData);
    super.onSaveInstanceState(outState);
}
Run Code Online (Sandbox Code Playgroud)

以及相关部分onCreate():

Data data;
FragmentManager fm = getSupportFragmentManager();
dataFragment = (DataFragment) fm.findFragmentByTag(TAG_DATA);
if (dataFragment == null) {
    // the Fragment is not attached, fetching data from DB
    DatabaseManager dbm = DatabaseManager.getInstance(this);
    data = dbm.getData();
} else {
    // the Fragment is attached, fetching the data from it
    data = dataFragment.getData();
    fm.beginTransaction().remove(dataFragment).commitNow();
}
Run Code Online (Sandbox Code Playgroud)

这在方向变化方面完美无瑕.

问题是,有时,当我的应用程序在后台并且我正在返回它时,dataFragment.getData()返回null.

换句话说,在下面的行中onCreate()有时datanull:

data = dataFragment.getData();
Run Code Online (Sandbox Code Playgroud)

这怎么可能?

它不会抛出NullPointerException,所以dataFragmentnull肯定的.

为什么它的初始化实例变量变成了null

Epi*_*rce 11

你遇到的是过程死亡.

从技术上讲,它也被称为"低内存条件".

保留的片段与应用程序一起被杀死,但FragmentActivity会重新创建保留的片段super.onCreate(),因此您可以通过其标记找到它,但其中的数据不会被初始化.

将应用程序置于后台,然后按Android Studio左下角的红色X以终止该过程.这再现了这种现象.

终止按钮

  • @Stallion保存到bundle(不推荐用于大型数据集,因为它可以在Nougat上崩溃),保存到共享pref,保存到JSON文件,保存到SQLite,保存到其他一些键值存储解决方案,如Paper或SnappyDb,保存到Realm,我不知道 (2认同)