代码之家  ›  专栏  ›  技术社区  ›  Emily

旋转屏幕时,我的ListView不会保存;使用parcelable interface和onSaveInstanceState

  •  2
  • Emily  · 技术社区  · 7 年前

    用户提交查询并搜索api后,将填充一个列表。但当我切换到风景时,它消失了。我需要设法保存它。我实现了一个可打包的接口,并添加了覆盖和恢复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");
    }
    

    和我的自定义类:

    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;
    }
    }
    
    3 回复  |  直到 7 年前
        1
  •  1
  •   firegloves    7 年前

    用这条线

    mAdapter = new BookAdapter(this, new ArrayList<Book>());
    

    您正在将书籍的空列表传递给ListView的适配器。因此,您的ListView将为空,因为它没有要显示的内容。

    myClass 正如我所见,这从来没有实例化过,所以您正在保存一个空对象。然后恢复此空对象。

    你必须做的是:

    • 创建书籍列表并将其放入 ArrayList
    • 先前创建的过程 给你的 Adapter
    • 阵列列表 onSaveInstanceState 方法
    • 要在旋转后恢复数据,必须注册 进入 onRestoreInstanceState 方法
    • 然后用还原的数据重新创建适配器,并将其重新分配给ListView

    在Book myClass级别声明ArrayList ArrayList<Book> bookList;

    尝试拆分此行

    分为以下两行:

    bookList = new ArrayList<Book>();
    mAdapter = new BookAdapter(this, bookList);
    

    然后在你的

    outState.putParcelableArrayList("bookList", bookList);
    

    在你的

    bookList = savedInstanceState.getParcelableArrayList("bookList");
    

    之后,你必须重新创建你的 适配器 ListView

    这应该是正确的方式

        2
  •  1
  •   Lakmal Weerasekara    7 年前

    首先创建公共 ArrayList<Book> list

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

    当应用程序开始旋转活动时 onSaveInstanceState

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        outState.putParcelableArrayList("obj", list);
        super.onSaveInstanceState(outState);
    }
    

    之后,您可以在发生时获得传递数据值 onRestoreInstanceState 活动的回调方法。如果可以使用Recyclerview代替Listview,那么应该将该列表设置为adapter并刷新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);
            }
        }
    }
    

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

        3
  •  0
  •   Kaushik NP    7 年前

    Orientation 在您的 Activity ,它会重新渲染布局。要停止此操作并保留布局视图,请在 android manifest file :

    android:configChanges="orientation"
    

    当方向改变时,这将覆盖默认行为。