在内存不足的情况下保存实例状态

时间:2015-05-04 16:58:05

标签: android android-fragments android-listview android-dialogfragment low-memory

我有一个由DialogFragment课程围绕的警报对话框。该对话框具有自定义布局,其中我显示了一个项目列表(我使用ListView和适当的适配器)。项目列表非常庞大且非常重要,因此我将其保存在Fragment DialogFragment的{​​{1}}课程中,就像在this example中一样。< / p>

一切都很完美,除了一种非常罕见的情况:当我打开对话框窗口打开应用程序时(按下&#34; home&#34;按钮)并且设备内存不足,它会杀死我的应用程序&# 39;过程当我稍后回到我的应用程序时,它会尝试重新创建对话框,但崩溃(我在对话框的onPause()适配器中得到NullPointerException),因为它无法恢复项目列表这是在我的左开对话框中显示的。发生这种情况是因为当系统终止我的应用程序进程时,我存储对话框状态的ListView也会被销毁,因此我的Fragment无法重新创建对话框,因为它没有来源列表适配器的数据。

我想要的是为我提供一个更好的方法来保存我的对话框窗口的状态,这样即使我的应用程序进程被杀死也可以重新创建它,或者如果项目列表显示我取消对话框的方法在恢复之前是DialogFragment(我的意思是在娱乐期间取消对话)。我不认为数据库是存储数据的好方法,因为这需要很长时间。如果没有适配器的信息,我更喜欢停止对话重建的方法。

更新:

在应用程序的生命周期中实施null来保存对象真是一个绝妙的主意。将对象写入Parcelable的速度很快(相信我,你不会看到生命周期变化之间的任何延迟,直到你开始不恰当地使用它),并且保存和恢复你的应用程序实例状态的过程是由Parcel流程管理,因此,即使不仅是您的ActivityManager,而且托管整个应用程序的流程也会被Android系统销毁,Activity维护ActivityManager如果在新进程中从头开始重新创建Parcel,则会保存对象并恢复其状态。非常感谢@Naveed鼓励我尝试这种做法!

对那些仍然没有注意到实际状态的人的注意事项:

在其生命周期事件中保存Activity的实例状态意味着维护仅对您的应用程序的当前用户界面或用户的当前进度有意义的信息更改,但不是必需的您的应用程序或用户在明确停止应用程序时(通过按后退按钮)并稍后再次启动它。这种特殊形式的信息应该保存在Activity对象的onSaveInstanceState()回调方法中,方法是使用原始Java类型的Bundle方法或实现put...()自定义类中的界面,稍后在ParcelableonCreate() callbakcs中恢复。

对用户而言重要的所有其他数据,无论是明确关闭您的应用程序还是仅将其短时间保留,都应保存在持久存储中,例如onRestoreInstanceState()数据库或{{ 1}}系统因此,只要用户或您的应用程序再次需要其先前的进度,它就可以恢复。 您应该在SQLite回调方法中保存这种形式的数据,因为它是保证在系统能够销毁您的应用程序进程之前调用的最后一种方法,以防它需要恢复某些资源。如果您选择将数据保存在SharedPreferences之后调用的方法中,即onPause()onPause(),则存在无法保存数据的巨大风险,因为这些方法可能永远不会如果系统决定在一些非常糟糕(但不一定罕见)的情况下立即杀死你的应用程序,就会被调用。

另一件事:请在存储少量数据时使用onStop(),因为它不是为存储列表,集合或捆绑而构建的。考虑花费几个小时来为您的应用程序实现onDestroy()数据库接口,并更轻松地使用它来维护大量信息。

1 个答案:

答案 0 :(得分:4)

由于内存问题,系统会在即将杀死您的应用时调用onSaveInstanceState。您可以在onSaveInstanceState中保存任何与州有关的信息。如果您的数据是基本类型,Parcelable或Serializable,则可以将其保存在一个包中。

重新创建活动后,您可以在onRestoreInstanceStateonCreatefragment life cycle中的以下任意内容中恢复该活动。

onCreate(Bundle) called to do initial creation of the fragment.

onCreateView(LayoutInflater, ViewGroup, Bundle) creates and returns the view  hierarchy associated with the fragment. 

onActivityCreated(Bundle) tells the fragment that its activity has    completed its own Activity.onCreate(). 

onViewStateRestored(Bundle)tells the fragment that all of the saved state of its view hierarchy has been restored.

如果您根本不想显示对话框。然后你可以在onResume中进行空检查,如果数据为空,则不要创建适配器,如果对话框可见则忽略该对话框。

更新:示例parcelable:

public class MyObject implements Parcelable {

        private String myString;
        private int myInt;

    protected MyObject(Parcel in) {
        myString = in.readString();
        myInt = in.readInt();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(myString);
        dest.writeInt(myInt);
    }

    @SuppressWarnings("unused")
    public static final Parcelable.Creator<MyObject> CREATOR = new Parcelable.Creator<MyObject>() {
        @Override
        public MyObject createFromParcel(Parcel in) {
            return new MyObject(in);
        }

        @Override
        public MyObject[] newArray(int size) {
            return new MyObject[size];
        }
    };
}