Android ListActivity:每次屏幕旋转后都会调用onCreate,选中的项目会重置,但视觉上仍保持选中状态

Android ListActivity: onCreate is called every time after screen rotation, selected item resets, but visually remains checked

如果屏幕不旋转,包含一个 TextView 和一个 ListView 对象的简单 ListActivity 工作正常。

问题描述。当运行第一次使用该应用程序时,TextView myText显示-1。有用。当点击不同的item时myText sets/shows被选中的item id(或position)的值。所以,它也有效。在某个时刻,例如当项目 Two 被选中并且 myText 显示 2 我旋转屏幕并且 myText 变成 -1 (因为 onCreate 再次触发),所以这意味着 ListView myList 清除选择,但项目 Two 仍然保持选中状态(绘制为选中的 RadioButton)。有什么问题? (P.S。同样的事情发生在 GridView 上)。

这是我的源代码:

activity_test.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".TestActivity">

    <include layout="@layout/content_test" />

</android.support.design.widget.CoordinatorLayout>

content_test.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".TestActivity">

    <TextView
        android:id="@+id/myText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <ListView
        android:id="@android:id/list"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/myText"
        android:choiceMode="singleChoice"/>
</RelativeLayout>

TestActivity.java

import android.app.ListActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class TestActivity extends ListActivity {

    static String[] items = {"Zero", "One", "Two"};

    TextView myText;
    ListView myList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        myList = (ListView) findViewById(android.R.id.list);
        setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_single_choice, items));

        myText = (TextView) findViewById(R.id.myListViewSelectedText);
        myText.setText(String.valueOf(myList.getSelectedItemPosition()));
    }

    @Override
    public void onListItemClick(ListView parent, View view, int position, long id) {
        myText.setText(String.valueOf(position));
    }
}

发生配置更改时,将重新创建所有活动以确保使用正确的资源。

一种保留您需要的状态的方法是覆盖 onSaveInstanceState() 将您想要的所有数据放入提供的 Bundle 参数。然后,当重新创建 activity 时,您可以从 onCreate().

中提供的 Bundle 参数中提取保存的值

只需保存所选列表元素的索引,然后在重新创建时将其重新设置。

试试这个

  <activity
        android:name=".TestActivity"
        android:label="@string/title_activity_test"
        android:theme="@style/AppTheme"
        android:configChanges="orientation|keyboardHidden|screenSize"/>

保存实例是更复杂的过程,@danail-alexiev 是正确的,在某些情况下您手动保存数据而不是恢复它。

但为什么 Checkbox 保持选中状态?简而言之,这是因为它有自己的 onSaveInstanceState 实现来处理它。并且有一些魔法调用它并将此 Parcelable 数据映射到视图 ID。你可以做简单的实验,创建一个空的应用程序,在布局中添加 EditText,没有 id - 运行 它,放一些文本,改变方向,boom - 数据丢失。然后用 id.

重试

您可以在这里找到很好的解释:Saving instance state