当屏幕方向改变时如何保存对象

37
如何在屏幕方向改变时保存对象,因为onRetainNonConfigurationInstancegetLastNonConfigurationInstance已经过时。并且不能与兼容性包android-support-v4.jarFragmentActivity一起使用,其中显示无法覆盖来自FragmentActivity的最终方法 开发者网站说:

使用新的Fragment API setRetainInstance(boolean)代替;

但我不知道如何使用setRetainInstance保存自定义对象 我的场景:
在我的活动中,我有一个带有进度对话框的AsyncTask。在这里,我需要处理方向更改。
为此,我从Mark Murphy,CommonsWare那里得到了一个非常好的答案
background-task-progress-dialog-orientation-change-is-there-any-100-working
具有示例项目

由于我正在使用兼容性包android-support-v4.jar,FragmentActivity,我无法重写onRetainNonConfigurationInstance
无法重写来自FragmentActivity的final方法

是否有其他替代方法可以保存我的自定义对象?

编辑: 我无法使我的AsyncTask任务可Parcelable(如果我没弄错的话),因为它使用了接口、上下文等。 我的AsyncTask

 public class CommonAsyncTask extends AsyncTask<Object, Object, Object>  {
        Context context;
        AsyncTaskServices callerObject;
        ProgressDialog progressDialog;
        String dialogMessag ; 
    ................

我正在寻找一个与onRetainNonConfigurationInstance方法相似的替代方法,该方法可以在方向更改时完全保存对象,并且稍后可以使用getLastNonConfigurationInstance检索

4个回答

43
你可以使用 onRetainCustomNonConfigurationInstance 来替代 onRetainNonConfigurationInstance(),然后使用 getLastCustomNonConfigurationInstance() 方法来获取先前保留的实例。

иҝҷдёҺй—®йўҳжҸҗеҮәиҖ…жҳҺзЎ®иҜ•еӣҫйҒҝе…Қзҡ„onRetainNonConfigurationInstance()е®Ңе…ЁзӣёеҗҢпјҲеңЁй—®йўҳзҡ„第дёҖеҸҘиҜқдёӯе°ұжҸҗеҲ°дәҶпјҒпјү - Timmmm
5
不,它们不是一样的。请查看文档:http://developer.android.com/reference/android/support/v4/app/FragmentActivity.html#onRetainCustomNonConfigurationInstance\(\)。原帖并没有说他试图避免使用onRetain...(),他只是说由于支持库中已将其声明为final,所以无法编译(这都是正确的)。我认为这个解决方案在迁移到新的操作方式时可以作为临时措施或解决方法。 - greg7gkb
16
有时候我觉得这些API被制作的比它们应该的要复杂。 - Phillip

12

有两种选择:

  1. 使用“Loader”。当重新创建时,FragmentActivity 会负责保存和恢复其状态。
  2. 使用没有视图的片段,并在其上调用 setRetainInstance(true)。兼容库源代码中有一个此类示例,名为 FragmentRetainInstanceSupport。

感谢 Nikolay Elenkov 指引我使用 loader,经过一番努力,我已经在 fragment 中使用了 loader - Labeeb Panampullan
你能告诉我你是如何处理进度对话框的显示/关闭的吗?因为在 onLoadFinished 中禁止使用这些片段事务。 - denis
使用FragmentTransaction.commitAllowingStateLoss()。听起来很脏,但似乎没有其他方法。或者更好的是,不要使用进度对话框。使用操作栏旋转器(不确定进度)或其他东西。对话框通常不值得麻烦。 - Nikolay Elenkov
有趣。这是最近添加的吗?我记得以前没有看到过。 - Nikolay Elenkov
@NikolayElenkov 如果你的片段没有视图,那么这不合适吗? - David Doria

5
当您的Fragment暂停时,它将调用此方法:
@Override
public void onSaveInstanceState(Bundle outState) {
    // Add variable to outState here
    super.onSaveInstanceState(outState);
}

变量outState将在Fragment重新启动时被传递到onCreate()方法中。
您可以保存任何基本类型或实现了Parcelable接口的数据。

2
看到我的编辑,我无法使我的AsyncTask任务可序列化(如果我没有错的话),因为它使用了接口、上下文等。 - Labeeb Panampullan
嗯...如果您不留下评论说明为什么要对答案进行负评,那么我们就无法知道它的错误之处。 - Graeme
我同意“附带评论的踩”会有所帮助。但是在这里,我不知道是什么/谁给了你那个(我看不到任何踩)。 - Labeeb Panampullan
+1 是指出 bundle 将在 onCreate 方法中可用,而不是我尝试的 onCreateView 或 onViewCreated。 - Bitcoin Cash - ADA enthusiast
当一个片段被替换时,这个方法也会被调用吗? - Kaveesh Kanwal
我不确定 - 我想不会,因为当一个片段被替换时,它会调用.remove()方法,有效地销毁它,它将永远不会被恢复。你可以自己试一下,这应该是一个相当容易的测试。 - Graeme

-1

好的,引用来自 Android Developers' References:

当活动从之前保存的状态重新初始化时,在 onStart() 后调用此方法,并在 savedInstanceState 中给出。 大多数实现将简单地使用 onCreate(Bundle) 来恢复其状态,但有时在所有初始化都完成后在此处执行此操作很方便,或者允许子类决定是否使用您的默认实现。 此方法的默认实现执行先前由 onSaveInstanceState(Bundle) 冻结的任何视图状态的恢复。

关于使用 onSaveInstanceState(),最好使用 onRestoreInstanceState() 来还原你的对象/事物。

参阅 Activity#onRestoreInstanceState()


看到我的编辑,我无法使我的AsyncTask任务可Parcelable化(如果我没有错的话),因为它使用接口、上下文等与onSaveInstanceState一起使用。 - Labeeb Panampullan
onRestoreInstanceState() 不是 onSaveInstanceState() 的替代品 - 实际上,没有 onSaveInstanceState() 它就完全无用。该引用只是提到在某些情况下使用 onRestoreInstanceState()onCreate() 更方便。 - Graeme

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接