如何在 Android 屏幕旋转上保存自定义 ArrayList?
Posted
技术标签:
【中文标题】如何在 Android 屏幕旋转上保存自定义 ArrayList?【英文标题】:How to save custom ArrayList on Android screen rotate? 【发布时间】:2012-09-12 07:12:51 【问题描述】:我有一个带有自定义对象的ArrayList
,我希望能够在屏幕旋转时保存和恢复这些对象。
我知道这可以用onSaveInstanceState
和onRestoreInstanceState
来完成,如果我要让ArrayList
成为它自己的类,它实现Parcelable
或Serializable
... 但是有没有办法在不创建另一个类的情况下这样做吗?
【问题讨论】:
【参考方案1】:您不需要创建新类来传递自定义对象的 ArrayList。您应该为您的对象简单地实现 Parcelable 类,并在onSaveInstanceState()
和onRestoreInstanceState()
中使用Bundle#putParcelableArrayList()。这个方法会自己存储一个 Parcelables 的 ArrayList。
因为 Parcelables(以及 Serializables 和 Bundles)的主题有时让我头疼,这里有一个 ArrayList 的基本示例,其中包含存储在 Bundle 中的自定义 Parcelable 对象。 (这是可剪切和粘贴运行的,无需布局。)
实现 Parcelable
public class MyObject implements Parcelable
String color;
String number;
public MyObject(String number, String color)
this.color = color;
this.number = number;
private MyObject(Parcel in)
color = in.readString();
number = in.readString();
public int describeContents()
return 0;
@Override
public String toString()
return number + ": " + color;
public void writeToParcel(Parcel out, int flags)
out.writeString(color);
out.writeString(number);
public static final Parcelable.Creator<MyObject> CREATOR = new Parcelable.Creator<MyObject>()
public MyObject createFromParcel(Parcel in)
return new MyObject(in);
public MyObject[] newArray(int size)
return new MyObject[size];
;
保存/恢复状态
public class Example extends ListActivity
ArrayList<MyObject> list;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
if(savedInstanceState == null || !savedInstanceState.containsKey("key"))
String[] colors = "black", "red", "orange", "cyan", "green", "yellow", "blue", "purple", "magenta", "white";
String[] numbers = "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten";
list = new ArrayList<MyObject>();
for(int i = 0; i < numbers.length; i++)
list.add(new MyObject(numbers[i], colors[i]));
else
list = savedInstanceState.getParcelableArrayList("key");
setListAdapter(new ArrayAdapter<MyObject>(this, android.R.layout.simple_list_item_1, list));
@Override
protected void onSaveInstanceState(Bundle outState)
outState.putParcelableArrayList("key", list);
super.onSaveInstanceState(outState);
【讨论】:
谢谢!但是,我迷失了private MyObject(Parcel in) color = in.readString(); number = in.readString();
位...这对字符串来说很容易,但是如何读取我的自定义数组列表? in.readArrayList(MyObject.class.getClassLoader())
给我一个错误。
嗯,在您的问题中,您询问了暗示ArrayList<MyObject>
的“带有自定义对象的ArrayList”,这个答案在Parcelable.Creator
中处理;但是您的评论只是问“我如何阅读我的自定义数组列表”,暗示MyArrayList
。你想扩展什么类? (抱歉,技术性很强,但我想尽快给你最好的答案。)
对不起,我的意思是 ArrayListreadArrrayList()
。查看我发布的示例活动中的onCreate()
。我检查:如果ArrayList<MyObject>
尚不存在,则创建它;如果确实存在,请在 ArrayList<MyObject>
和 list = savedInstanceState.getParcelableArrayList("key");
中读取。这有意义吗?如果有帮助,我可以轻松地更详细地评论我的示例。
@Sam 您如何将 Parcelable 与字符串的 ArrayList 一起使用,而不是自定义对象?【参考方案2】:
您可以使用onRetainNonConfigurationInstance()
。它允许您在配置更改之前保存任何对象,并在之后使用getLastNonConfigurationInstanceState
() 恢复它。
活动内部:
@Override
public Object onRetainNonConfigurationInstance()
return myArrayList;
内部onCreate()
:
try
ArrayList myArrayList = (ArrayList)getLastNonConfigurationInstance();
catch(NullPointerException e)
处理运行时更改:http://developer.android.com/guide/topics/resources/runtime-changes.html 文档:http://developer.android.com/reference/android/app/Activity.html#onRetainNonConfigurationInstance%28%29
【讨论】:
哇,从来不知道这个功能!超级简单,正是我所需要的......但是,我看到它已被弃用...... 不幸的是,它仍然有效,并且没有其他简单的方法可以做到这一点。山姆的答案是我发现的唯一其他方法,但实施起来要困难得多。 如果你正在使用 Fragments,你可以使用Fragment.setRetainInstance(true)
代替,这是它的更新版本(但仅适用于 Fragments)。文档:developer.android.com/reference/android/app/…
只有在不幸没有将片段添加到后台堆栈时才有效【参考方案3】:
public void onSaveInstanceState(Bundle outState)
super.onSaveInstanceState(outState);
ArrayList<Integer> id=new ArrayList<>();
ArrayList<String> title=new ArrayList<>();
for(int i=0;i<arr.size();i++)
id.add(arr.get(i).id);
title.add(arr.get(i).title);
outState.putIntegerArrayList("id",id);
outState.putStringArrayList("title",title);
【讨论】:
欢迎来到 Stack Overflow。您能否详细说明一下此解决方案如何回答问题? 这可能有效。我还没有尝试过。不过,这真是个黑客。【参考方案4】:是的,您可以将复合对象保存在共享首选项中。比方说:
Student mStudentObject = new Student();
SharedPreferences appSharedPrefs = PreferenceManager
.getDefaultSharedPreferences(this.getApplicationContext());
Editor prefsEditor = appSharedPrefs.edit();
Gson gson = new Gson();
String json = gson.toJson(mStudentObject);
prefsEditor.putString("MyObject", json);
prefsEditor.commit();
现在您可以将对象检索为:
SharedPreferences appSharedPrefs = PreferenceManager
.getDefaultSharedPreferences(this.getApplicationContext());
Editor prefsEditor = appSharedPrefs.edit();
Gson gson = new Gson();
String json = appSharedPrefs.getString("MyObject", "");
Student mStudentObject = gson.fromJson(json, Student.class);
【讨论】:
这样做的坏主意 - 取决于要保存的列表的大小。 SharedPreferences 是一个 XML 文件,它不是为存储大量数据集而设计的。以上是关于如何在 Android 屏幕旋转上保存自定义 ArrayList?的主要内容,如果未能解决你的问题,请参考以下文章
Android jetpack viewModel 屏幕旋转数据如何保存。