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

时间:2016-09-30 07:05:07

标签: android android-fragments

作为Intent的替代方案,我在Fragment重新创建期间将数据保存在保留的无头Activity中(我保存的对象可能非常大而且不会符合Intent的大小限制,我认为这比序列化 - 反序列化为JSON更快,例如)。

我从this Google documentation得到了这个想法,虽然我的实现有点不同。

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

我在Fragment的{​​{1}}方法中将我的数据保存到此onSaveInstanceState()

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); } 的相关部分:

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(); } 会返回dataFragment.getData()

换句话说,null中的以下行有时onCreate()data

null

这怎么可能?

它不会抛出data = dataFragment.getData(); ,因此NullPointerException肯定不是dataFragment

为什么其初始化的实例变量变为null

2 个答案:

答案 0 :(得分:10)

您遇到的是过程死亡。

从技术上讲,它也被称为“低内存条件”。

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

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

terminate button

答案 1 :(得分:-2)

如果活动在之前被销毁后重新创建,则可以从系统传递活动的Bundle中保存您的状态。 onCreate()和onRestoreInstanceState()回调方法都接收包含实例状态信息的相同Bundle。

显然,无论系统是创建活动的新实例还是重新创建前一个实例,都会调用onCreate()方法,在尝试读取之前,需要检查状态Bundle是否为null。如果它为null,则系统正在创建活动的新实例,而不是恢复已销毁的先前实例。 在oncreate()中:

Data data;
FragmentManager fm = getSupportFragmentManager();
dataFragment = (DataFragment) fm.findFragmentByTag(TAG_DATA);
**if (dataFragment.getData()== 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();
}