我的 ListView 不会在旋转屏幕时保存;使用 parcelable 接口和 onSaveInstanceState
My ListView won't save upon rotating the screen; using parcelable interface and onSaveInstanceState
用户提交查询并搜索 api 后,会填充一个列表。但是当我切换到横向时它就消失了。我需要以某种方式保存它。我已经实现了一个 parcelable 接口并添加了覆盖和恢复 onSaveInstanceState 的方法。我这里的内容对我的应用程序的性能没有影响,不幸的是,我对新代码还不够熟悉,无法弄清楚我做错了什么。我在网上找到的大部分内容都假设我知道的比我知道的多哈哈。任何建议表示赞赏。谢谢!
public class MainActivity extends AppCompatActivity {
Book myClass;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Find the ListView.xml in the view hierarchy.
ListView listItemView = (ListView) findViewById(R.id.list);
// Shows an empty text view when there's nothing to show
mEmptyStateTextView = (TextView) findViewById(R.id.empty_view);
listItemView.setEmptyView(mEmptyStateTextView);
// Create a new adapter that takes an empty list of books as input
mAdapter = new BookAdapter(this, new ArrayList<Book>());
// Hide loading indicator because the data has been loaded
View loadingIndicator = findViewById(R.id.loading_indicator);
loadingIndicator.setVisibility(View.GONE);
// Populates the adapter with the list view xml file
listItemView.setAdapter(mAdapter);
handleIntent(getIntent());
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable("obj", myClass);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
myClass=savedInstanceState.getParcelable("obj");
}
还有我的习惯class:
public class Book implements Parcelable {
private int mData;
// Book title
private String mTitle;
// Book author
private String mAuthor;
/**
* Create a new Book object
* @param title is the title of the book
* @param author is the author of the book
*/
public Book(String title, String author) {
mTitle = title;
mAuthor = author;
}
//Get the title of the book.
public String getTitle() {
return mTitle;
}
//Get the author of the book.
public String getAuthor() {
return mAuthor;
}
protected Book(Parcel in) {
mTitle = in.readString();
mAuthor = in.readString();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mTitle);
dest.writeString(mAuthor);
}
public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>() {
@Override
public Book createFromParcel(Parcel in) {
return new Book(in);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
}
我的列表适配器:
public class BookAdapter extends ArrayAdapter<Book> {
//constructor
public BookAdapter(Activity context, ArrayList<Book> books) {
super(context, 0, books);
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
// control-O automatically created
View listItemView = convertView;
if(listItemView == null) {
listItemView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent, false);
}
// Get the book at the current position on the list
Book currentBook = getItem(position);
// Find the TextView in the list_item.xml with this ID
TextView titleTextView = (TextView) listItemView.findViewById(R.id.title_text);
// Get the title from the current Book object and set it on the TextView
titleTextView.setText(currentBook.getTitle());
// Find the TextView in the list_item.xml with this ID
TextView authorTextView = (TextView) listItemView.findViewById(R.id.author_text);
// Get the title from the current Book object and set it on the TextView
authorTextView.setText(currentBook.getAuthor());
// Return the whole list item layout (containing 2 TextViews)
// so that it can be shown in the ListView
return listItemView;
}
}
用这条线
mAdapter = new BookAdapter(this, new ArrayList<Book>());
您正在将 Book 的空列表传递给 ListView 的适配器。所以你的 ListView 将是空的,因为它没有什么可显示的。
然后你保存 myClass
,正如我所见,它从未被实例化,所以你保存了一个空对象。然后你恢复这个空对象。
你必须做的是:
- 创建图书列表并将它们放入
ArrayList
- 将之前创建的
ArrayList
传递给您的 Adapter
- 要在旋转之前保存数据,您必须将
ArrayList
保存到 onSaveInstanceState
方法中
- 要在旋转后恢复数据,您必须将
ArrayList
重新设置为 onRestoreInstanceState
方法
- 然后使用恢复的数据重新创建您的适配器并将其重新分配给您的 ListView
更新
在 Book myClass 级别声明您的 ArrayList ArrayList<Book> bookList;
尝试拆分此行
mAdapter = new BookAdapter(this, new ArrayList<Book>());
进入这两行:
bookList = new ArrayList<Book>();
mAdapter = new BookAdapter(this, bookList);
然后在你的 onSaveInstanceState
outState.putParcelableArrayList("bookList", bookList);
在你的 onRestoreInstanceState
bookList = savedInstanceState.getParcelableArrayList("bookList");
之后您必须重新创建 Adapter
并将其重新分配给您的 ListView
这应该是正确的方法
问题是,当 Activity
中的 Orientation
发生变化时,它会重新呈现布局。要停止并保留布局视图,请在 android manifest file
中添加以下内容:
android:configChanges="orientation"
这将覆盖方向更改时的默认行为。
先创建public ArrayList<Book> list
对象,然后设置为Adapter
ArrayList<Book> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ArrayList list = new ArrayList<Book>();
list = getListData()// assign list values to list object
.....
mAdapter = new BookAdapter(this, list);
.....
.....
listItemView.setAdapter(mAdapter);
}
当应用旋转 activity 进入 onSaveInstanceState
并销毁 activity.therefore 时,您应该将该列表值设置为 saveInstatantState 对象
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putParcelableArrayList("obj", list);
super.onSaveInstanceState(outState);
}
之后你可以在 Activity.and 上发生 onRestoreInstanceState
回调方法时获取传递数据值,你应该将该列表设置为适配器并刷新 Listview,如果你可以使用 Recyclerview 而不是 Listview。
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (savedInstanceState != null) {
list = savedInstanceState.getParcelableArrayList("obj");
if (list != null) {
mAdapter.addAll(list);
......
listItemView.setAdapter(mAdapter);
}
}
}
我希望你能用这个解决方案得到一个解决方案,这不是完整的源代码更正。这是你应该在技术上做的解决方案。
用户提交查询并搜索 api 后,会填充一个列表。但是当我切换到横向时它就消失了。我需要以某种方式保存它。我已经实现了一个 parcelable 接口并添加了覆盖和恢复 onSaveInstanceState 的方法。我这里的内容对我的应用程序的性能没有影响,不幸的是,我对新代码还不够熟悉,无法弄清楚我做错了什么。我在网上找到的大部分内容都假设我知道的比我知道的多哈哈。任何建议表示赞赏。谢谢!
public class MainActivity extends AppCompatActivity {
Book myClass;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Find the ListView.xml in the view hierarchy.
ListView listItemView = (ListView) findViewById(R.id.list);
// Shows an empty text view when there's nothing to show
mEmptyStateTextView = (TextView) findViewById(R.id.empty_view);
listItemView.setEmptyView(mEmptyStateTextView);
// Create a new adapter that takes an empty list of books as input
mAdapter = new BookAdapter(this, new ArrayList<Book>());
// Hide loading indicator because the data has been loaded
View loadingIndicator = findViewById(R.id.loading_indicator);
loadingIndicator.setVisibility(View.GONE);
// Populates the adapter with the list view xml file
listItemView.setAdapter(mAdapter);
handleIntent(getIntent());
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable("obj", myClass);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
myClass=savedInstanceState.getParcelable("obj");
}
还有我的习惯class:
public class Book implements Parcelable {
private int mData;
// Book title
private String mTitle;
// Book author
private String mAuthor;
/**
* Create a new Book object
* @param title is the title of the book
* @param author is the author of the book
*/
public Book(String title, String author) {
mTitle = title;
mAuthor = author;
}
//Get the title of the book.
public String getTitle() {
return mTitle;
}
//Get the author of the book.
public String getAuthor() {
return mAuthor;
}
protected Book(Parcel in) {
mTitle = in.readString();
mAuthor = in.readString();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mTitle);
dest.writeString(mAuthor);
}
public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>() {
@Override
public Book createFromParcel(Parcel in) {
return new Book(in);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
}
我的列表适配器:
public class BookAdapter extends ArrayAdapter<Book> {
//constructor
public BookAdapter(Activity context, ArrayList<Book> books) {
super(context, 0, books);
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
// control-O automatically created
View listItemView = convertView;
if(listItemView == null) {
listItemView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent, false);
}
// Get the book at the current position on the list
Book currentBook = getItem(position);
// Find the TextView in the list_item.xml with this ID
TextView titleTextView = (TextView) listItemView.findViewById(R.id.title_text);
// Get the title from the current Book object and set it on the TextView
titleTextView.setText(currentBook.getTitle());
// Find the TextView in the list_item.xml with this ID
TextView authorTextView = (TextView) listItemView.findViewById(R.id.author_text);
// Get the title from the current Book object and set it on the TextView
authorTextView.setText(currentBook.getAuthor());
// Return the whole list item layout (containing 2 TextViews)
// so that it can be shown in the ListView
return listItemView;
}
}
用这条线
mAdapter = new BookAdapter(this, new ArrayList<Book>());
您正在将 Book 的空列表传递给 ListView 的适配器。所以你的 ListView 将是空的,因为它没有什么可显示的。
然后你保存 myClass
,正如我所见,它从未被实例化,所以你保存了一个空对象。然后你恢复这个空对象。
你必须做的是:
- 创建图书列表并将它们放入
ArrayList
- 将之前创建的
ArrayList
传递给您的Adapter
- 要在旋转之前保存数据,您必须将
ArrayList
保存到onSaveInstanceState
方法中 - 要在旋转后恢复数据,您必须将
ArrayList
重新设置为onRestoreInstanceState
方法 - 然后使用恢复的数据重新创建您的适配器并将其重新分配给您的 ListView
更新
在 Book myClass 级别声明您的 ArrayList ArrayList<Book> bookList;
尝试拆分此行
mAdapter = new BookAdapter(this, new ArrayList<Book>());
进入这两行:
bookList = new ArrayList<Book>();
mAdapter = new BookAdapter(this, bookList);
然后在你的 onSaveInstanceState
outState.putParcelableArrayList("bookList", bookList);
在你的 onRestoreInstanceState
bookList = savedInstanceState.getParcelableArrayList("bookList");
之后您必须重新创建 Adapter
并将其重新分配给您的 ListView
这应该是正确的方法
问题是,当 Activity
中的 Orientation
发生变化时,它会重新呈现布局。要停止并保留布局视图,请在 android manifest file
中添加以下内容:
android:configChanges="orientation"
这将覆盖方向更改时的默认行为。
先创建public ArrayList<Book> list
对象,然后设置为Adapter
ArrayList<Book> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ArrayList list = new ArrayList<Book>();
list = getListData()// assign list values to list object
.....
mAdapter = new BookAdapter(this, list);
.....
.....
listItemView.setAdapter(mAdapter);
}
当应用旋转 activity 进入 onSaveInstanceState
并销毁 activity.therefore 时,您应该将该列表值设置为 saveInstatantState 对象
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putParcelableArrayList("obj", list);
super.onSaveInstanceState(outState);
}
之后你可以在 Activity.and 上发生 onRestoreInstanceState
回调方法时获取传递数据值,你应该将该列表设置为适配器并刷新 Listview,如果你可以使用 Recyclerview 而不是 Listview。
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (savedInstanceState != null) {
list = savedInstanceState.getParcelableArrayList("obj");
if (list != null) {
mAdapter.addAll(list);
......
listItemView.setAdapter(mAdapter);
}
}
}
我希望你能用这个解决方案得到一个解决方案,这不是完整的源代码更正。这是你应该在技术上做的解决方案。