如果状态是由我的类组成的,如何在Android中的方向更改期间保存状态?

时间:2010-10-12 14:55:51

标签: android

我正在研究Android为我的应用程序处理方向更改的方式(我发现它重新开始了方向更改的主要活动。我已经看到你可以覆盖方法

protected void onSaveInstanceState(Bundle outState)

要保存内容,请进入onStart。问题是我使用自定义适配器查看自定义对象和列表视图。一切都在这些对象的ArrayList中,但我注意到你不能在bundle中放置任意对象!那么如何保存状态呢?

5 个答案:

答案 0 :(得分:137)

您是否尝试过使用:它的解决方法,

<activity name= ".YourActivity" android:configChanges="orientation|screenSize"/>

在清单文件中?

默认情况下不起作用,因为当您更改方向onCreate时,将再次调用它并重新绘制视图。

如果编写此参数无需在Activity中处理,框架将处理其余的事情。 如果方向改变,它将保持屏幕或布局的状态。

注意如果您使用横向模式的其他布局,则通过添加这些参数,将不会调用横向模式的布局。

Other way Another way

答案 1 :(得分:42)

编辑:在较新版本的Android和兼容性库中,retained fragments通常是处理在活动销毁/创建过程中保持昂贵重建数据的最佳方式。正如Dianne所指出的那样,保留非配置数据是为了优化缩略图生成之类的事情,这些事情由于性能原因而很好地保存,但如果需要重做,则对于您的活动运行并不重要 - 它不能代替正确保存和恢复活动状态。

但回到2010年我第一次回答这个问题时: 如果要保留自己的(非视图状态)数据,可以使用onRetainNonConfigurationInstance()实际传递任意对象以进行方向更改。见this Android Developers blog post。注意不要将任何视图或其他引用放在您传递的对象中的预旋转上下文/活动中,否则您将阻止这些对象被垃圾回收并最终耗尽内存(这称为{{ 3}})。

答案 2 :(得分:16)

首先,您需要确定应用中的“状态”。你还没有说出你实际在做什么,但让我假设对象的ArrayList是用户正在使用的状态。

其次,确定这个州的生命周期实际上是什么。它真的与那项活动有关吗?或者,如果用户说电池电量不足,用户不会丢失,设备将关闭,之后他们会返回您的应用程序?如果前者onSaveInstanceState()是正确的;如果是后者,您需要在onPause()中保存到持久存储。

对于具有自定义对象的onSaveInstanceState(),关键是实现Parcelable接口。这涉及在Parcelable上实现方法,以及在类中创建静态CREATOR对象。这是典型的简单Parcelable类的代码:

https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/content/ComponentName.java

关键功能是Parcelable实现:

https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/content/ComponentName.java#317

和CREATOR静态类:

https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/content/ComponentName.java#355

(静态writeToParcel()readFromParcel()只是为该类所做的便利,而不是必需的。)

现在您已经拥有了它,您可以将整个对象的ArrayList放入已保存的状态Bundle Bundle.putParcelableArrayList

http://developer.android.com/reference/android/os/Bundle.html#putParcelableArrayList(java.lang.String, java.util.ArrayList)

Activity.onCreate()中,检查您是否有savedState Bundle,如果是,请尝试从中检索ArrayList并在找到时使用它,为新活动创建新适配器和列表视图用来显示它。

答案 3 :(得分:3)

  

但我注意到你不能在捆绑中放置任意对象!

首先制作自定义对象Parcelable 然后你可以将它们放入一个包中。

  

所有内容都在这些对象的ArrayList中

您可以在bundle中使用putParcelableArrayList方法来存储自定义“parcelable”对象的ArrayList。

答案 4 :(得分:0)

对于简单数据,活动可以使用onSaveInstanceState()方法并从onCreate()中的包中还原其数据,但是此方法仅适用于可以先序列化然后反序列化的少量数据,而不适用于可能很大的数据大量的数据,例如用户列表或位图。

The ViewModel class allows data to survive configuration changes such as screen rotations.
Architecture Components provides ViewModel helper class for the UI controller that is responsible for preparing data for the UI.

**Example**:

如果需要在应用程序中显示用户列表,请确保分配职责来获取并保留用户列表的ViewModel,而不是活动或片段,如以下示例代码所示。

public class MyViewModel extends ViewModel {
    private MutableLiveData<List<User>> users;
    public LiveData<List<User>> getUsers() {
        if (users == null) {
            users = new MutableLiveData<List<User>>();
            loadUsers();
        }
        return users;
    }

    private void loadUsers() {
        // Do an asynchronous operation to fetch users.
    }
}

public class MyActivity extends AppCompatActivity {
    public void onCreate(Bundle savedInstanceState) {
        // Create a ViewModel the first time the system calls an activity's onCreate() method.
        // Re-created activities receive the same MyViewModel instance created by the first activity.

        MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
        model.getUsers().observe(this, users -> {
            // update UI
        });
    }
}