簡體   English   中英

如果狀態是由我的班級構成的,如何在Android方向更改期間保存狀態?

[英]How to save state during orientation change in Android if the state is made of my classes?

我當時正在研究Android處理應用程序方向變化的方式(我發現它會在方向變化時重新啟動mainactivity。我發現您可以覆蓋該方法

protected void onSaveInstanceState(Bundle outState)

要保存內容,請使用onStart。 問題是我有使用自定義對象的視圖和使用自定義適配器的列表視圖。 一切都在這些對象的ArrayList中,但是我注意到您不能將任意對象放入包中! 那么如何保存狀態?

您是否嘗試過使用:它的解決方法,

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

在清單文件中?

默認情況下它不起作用,因為,當您更改方向時,將再次調用onCreate並重繪視圖。

如果您在Activity中無需處理此參數,則框架將處理其余工作。 如果更改方向,它將保留屏幕或布局的狀態。

注意如果橫向模式使用其他布局,則通過添加這些參數,不會調用橫向模式的布局。

另一種方法另一種方法

編輯:在較新版本的Android上以及使用兼容性庫, 保留的碎片通常是處理在活動破壞/創建過程中保持昂貴的重新生成數據的最佳方法。 正如Dianne指出的那樣,保留非配置數據是為了優化諸如縮略圖生成之類的東西,這些東西出於性能方面的考慮可以很好地保存,但對於需要重做的活動功能而言並不重要-它不能代替正確保存和恢復活動狀態。

但是回到2010年我第一次回答這個問題時:
如果要保留自己的(非視圖狀態)數據,則實際上可以使用onRetainNonConfigurationInstance()傳遞一個專門用於方向更改的任意對象。 請參閱此Android開發者博客文章 請注意不要在傳遞的對象中放置任何對旋轉前的Context / Activity的視圖或其他引用,否則您將防止垃圾回收這些對象並最終導致內存不足(這稱為上下文泄漏) )。

首先,您需要確定應用程序中的實際“狀態”。 您沒有說您實際在做什么,但是讓我假設對象的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.putParcelableArrayList的保存狀態Bundle Bundle.putParcelableArrayList

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

Activity.onCreate() ,檢查是否有savedState Bundle ,如果有,請嘗試從中檢索ArrayList並使用它(如果找到),為新的活動創建一個新的適配器和列表視圖,以用於顯示它。

但我注意到您不能在捆綁包中放置任意對象!

首先,將自定義對象設置為Parcelable
然后,您可以將它們捆綁在一起。

一切都在這些對象的ArrayList中

您可以在捆綁軟件中使用putParcelableArrayList方法存儲自定義“可打包”對象的ArrayList。

使用Google的Gson將對象寫入JSON字符串,然后將它們另存為字符串。 然后,在重建活動/片段時,從保存的JSON字符串重新構建它們

import com.google.gson.Gson;

public class MyClass {
    private int a;
    private String s;
    private OtherSerializableClass other;
    private List<String> list;

    public String toJson() {
        return new Gson().toJson(this);
    }

    public static ChatAPI_MessagesArray fromJson(String json){
       return new Gson().fromJson(json, YourClass.class);
    }

    // Getters
    ...

    // Setters
    ...
}

對於簡單數據,活動可以使用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
        });
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM