我的ListView在旋转屏幕时无法保存;使用parcelable接口和onSaveInstanceState

时间:2017-09-20 17:52:18

标签: android listview screen-orientation

用户提交查询并搜索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");
}

我的自定义课程:

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 个答案:

答案 0 :(得分:0)

使用此行

//table      
var table = [
"Lyn", "22", "F", 1, 1,
"May", "32", "F", 18, 1,
"Sam", "27", "F", 1, 2,
"Sham", "23", "F", 2, 2,
"Hrs", "22", "M", 13, 2
];

// function calling starts here..

            for ( var i = 0; i < table.length; i += 5 ) {

                var element = document.createElement( 'div' );
                element.className = 'element';

                var number = document.createElement( 'div' );
                number.className = 'number';
                number.textContent = (i/5) + 1;
                element.appendChild( number );

                var symbol = document.createElement( 'div' );
                symbol.className = 'symbol';
                symbol.textContent = table[ i ];
                element.appendChild( symbol );

                var details = document.createElement( 'div' );
                details.className = 'details';
                details.innerHTML = table[ i + 1 ] + '<br>' + table[ i + 2 ];
                element.appendChild( details );
                element.CheckColour(details);  /*help me check this */

                /*CheckColour function, help me check this too if there is any error*/
                function CheckColour()
                {
                  var element, number, symbol, details;

                  if(details == "M")
                  element.style.backgroundColor = 'rgba(0,191,255,0)';
                  else
                  element.style.backgroundColor = 'rgba(255,105,180,0)';
                }

您将Book的空列表传递给ListView的适配器。所以你的ListView将是空的,因为它没有任何东西可以显示。

然后保存从未实例化的mAdapter = new BookAdapter(this, new ArrayList<Book>()); ,因为我可以看到,所以你要保存一个空对象。然后恢复此空对象。

你必须做的是:

  • 创建一个Book列表并将其放入myClass
  • 将之前创建的ArrayList传递给您的ArrayList
  • 要在轮播前保存数据,您必须将Adapter保存到ArrayList方法
  • 要在轮播后恢复数据,您必须将onSaveInstanceState恢复为ArrayList方法
  • 然后使用恢复的数据重新创建适配器并将其重新分配给ListView

<强>更新

在Book myClass level onRestoreInstanceState

中声明您的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

这应该是正确的方式

答案 1 :(得分:0)

问题是,当您Orientation更改Activity时,它会重新呈现布局。要停止并保留布局视图,请在android manifest file

中添加以下内容
android:configChanges="orientation"

这将覆盖方向更改时的默认行为。

答案 2 :(得分:0)

首先创建公共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);
}

当app将旋转活动转为onSaveInstanceState并销毁活动时。因此,您应将该列表值设置为saveInstatantState对象

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

之后,您可以在Activity上发生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);
        }
    }
}

我希望你能得到这个解决方案的解决方案,这不是全源修正。这是你应该在技术上做的解决方案。