Search code examples
androidlistviewadapterorientationrestore

Restore items and scroll position in listview on orientation change


I tried, by several means, to restore data of a listview when the user rotate his phone..However, I have some difficulties due to the fact that when I turn the screen once, it works, but when I turn it over another time, it no longer works. In addition, I tried to restore the scroll position but without success.

So I would like to know the best way to do this.


My code:

private ListView item_container;
private ArrayList<Song.Hits> values;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    item_container = findViewById(R.id.bottom_popup_container);
}

And when I finish to retrieve data from an API, I load them into the listview (and I save the data):

@Override
public void onRequestFinish(ArrayList<Song.Hits> hits) {
    if (!hits.isEmpty()) {
        CAdapter adapter = new CAdapter(hits);
        item_container.setAdapter(adapter);
        values = adapter.getHits();
    };
}

Finally, I overwrite these 2 methods to save the position and the items of the listview.

    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        outState.putParcelableArrayList("list",  values);
        outState.putParcelable("pos", item_container.onSaveInstanceState());
        super.onSaveInstanceState(outState);
    }

    @Override
    protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
            ArrayList<Song.Hits> values = savedInstanceState.getParcelableArrayList("list");
            if (values != null) {
                CAdapter adapter = new CAdapter(values);
                item_container.setAdapter(adapter);
                item_container.onRestoreInstanceState(savedInstanceState.getParcelable("pos"));
            }
    }

Solution

  • To an unrelated degree, you should probably be using RecyclerView instead of ListView, which nowadays also supports a custom state restoration policy so that the scroll state is automatically preserved until data is set.

    Anyways, following current approach, should be as simple as

    @Override
    protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        ArrayList<Song.Hits> values = savedInstanceState.getParcelableArrayList("list");
    

    should be

    @Override
    protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        values = savedInstanceState.getParcelableArrayList("list");