我的 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);
        }
    }
}

我希望你能用这个解决方案得到一个解决方案,这不是完整的源代码更正。这是你应该在技术上做的解决方案。