在方向更改时恢复列表视图中的项目和滚动位置

Restore items and scroll position in listview on orientation change

我尝试通过多种方式在用户旋转 phone 时恢复列表视图的数据。但是,我遇到了一些困难,因为当我转动屏幕一次时,它就可以工作,但是当我再次将其翻转时,它不再起作用。另外,我尝试恢复滚动位置,但没有成功。

所以我想知道最好的方法。


我的代码:

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

当我完成从 API 中检索数据时,我将它们加载到列表视图中(并保存数据):

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

最后,我覆盖了这2个方法来保存列表视图的位置和项目。

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

您还应该更新 OnCreate 方法或覆盖 OnPostCreate 方法,并在检查 savedInstanceState!=null 时添加您在 onRestoreInstanceState 中使用的逻辑

您应该在 onCreate 上进行相同的检查,因为 onRestoreInstanceState 并不总是被调用,这有点棘手。

您可以从文档中查看:

This method is called after onStart() when the activity is being re-initialized from a previously saved state, given here in savedInstanceState. Most implementations will simply use onCreate(Bundle) to restore their state, but it is sometimes convenient to do it here after all of the initialization has been done or to allow subclasses to decide whether to use your default implementation. The default implementation of this method performs a restore of any view state that had previously been frozen by onSaveInstanceState(Bundle).

将你的逻辑移到 onCreate 就可以了

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

    item_container = findViewById(R.id.bottom_popup_container);

    if (savedInstanceState != null) {
        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"));
        }
    }
}

在不相关的程度上,您可能应该使用 RecyclerView 而不是 ListView,它现在也支持自定义状态恢复策略,以便在设置数据之前自动保留滚动状态。

无论如何,按照目前的方法,应该像

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

应该是

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