安卓屏幕旋转后ListView消失

10
在我的布局中,我有一些按钮来进行选择,然后有一个按钮来执行对数据库的查询。这个查询的结果会显示在布局内的一个 ListView 中。
问题是,如果在执行查询后旋转屏幕,ListView 会消失,必须重新执行查询。
我认为这是因为活动重新启动了。根据这里的建议,我在清单中的活动中添加了 android:configChanges="orientation|keyboardHidden",并在我的代码中添加了:
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
      super.onConfigurationChanged(newConfig);
      setContentView(R.layout.mylayout);

    }

但是这不起作用。

以下是我的活动的完整代码:

public class MyClass extends ListActivity implements OnClickListener, OnCheckedChangeListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mylayout);

        // Creates the buttons and setOnClickListener and setOnCheckedChangeListener
    }

    @Override
    public void onClick(View v) {

        // Manages the buttons and their functions

    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
        // See what group in radio group is checked
    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        // After pressing one button, a query is made and a listview is shown. 
        // This it to handle the user choice after he clicks an item on the listview

    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
      super.onConfigurationChanged(newConfig);
      setContentView(R.layout.mylayout);

    }
}

这很奇怪,因为我有一些类似的活动:

public class AtoZ extends ListActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.atoz);



    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        // TODO Auto-generated method stub
        super.onListItemClick(l, v, position, id);

    }

}   

这也执行了一个查询到数据库,将其显示在ListView上,然后处理用户的选择。如果我旋转屏幕,ListView仍然显示。

我该怎么办?


为什么在 onConfigurationChanged 方法中将布局设置为 R.layout.nutrient(而不是在 onCreate 方法中设置为 R.layout.mylayout)? - Sameer
@Sameer 忘记改那个了。已经更正。 - Favolas
你如何将数据放入ListView中?您是否将其绑定到数据库游标? - Sameer
@Sameer 是的。Cursor query = baseDados.getData(1,0,null); MyAdapt cursorAdapter = new MyAdapt(this, query,0); listContent.setAdapter(cursorAdapter);MyAdapt 中,视图与光标绑定。 - Favolas
如果您不更改布局,请删除onConfigurationchange方法。在清单文件中编写就足够了。 - Kamal
@Kamal移除后,屏幕旋转后,ListView消失了。 - Favolas
5个回答

9

在Manifest文件中的Activity中使用configChanges。

<activity
...
...
android:configChanges="orientation|screenSize|keyboard">
</activity

这对我有用。

5
有两种方法可以解决你的问题:
解决方法A:
1. 在你的manifest xml文件中添加android:configChanges="orientation|keyboardHidden"。 2. 删除onConfigurationChanged(Configuration newConfig)函数。
因为onCreate()只会在Activity初始化时调用一次。而onConfigurationChanged()会重新加载和填充新的视图R.layout.mylayout,但数据为空=>你的列表不会绑定任何数据。
解决方法B:
将已经写在onCreate()中的数据绑定代码移动到重载方法onStart()onResume()中。我建议你在数据绑定方面使用onStart()
你应该查看开发页面Android Activity生命周期 (更新):
因为你在点击列表项上的搜索按钮时加载了listContent,所以你必须在活动中维护数据,以便从中重新构建列表(例如:搜索字符串)。然后在onStart()中从这些数据重建你的列表。
但是当点击列表项更改整个列表时,你的逻辑有点奇怪。请注意:onListItemClick(..)也会在单击列表项上的按钮时触发。

求解器A和求解器B都没有起作用。我把所有的代码放在onStart()里面,但是旋转后还是一样的结果。 - Favolas
1
您可以在以下链接中查看更多有关 setRetainInstance 的解决方案。 - Kelvin Trinh
抱歉晚了,因为度假不在。是的,我在重写方法 protected void onListItemClick(..) 中调用了 super.onListItemClick(l, v, position, id);。抱歉,我不知道如何使用 setRetainInstance。现在我想保存 ListView 的结果,这样当用户旋转屏幕并切换到横向布局时,它会显示在纵向模式下显示的 ListView。 - Favolas
1
你能否发布你的Manifest xml以及一些加载列表的代码;并且发布你的Android SDK版本?我看到你在点击ListItem时加载了列表视图?这是相当奇怪的方式,因为此时新的列表实例被替换了。 - Kelvin Trinh
谢谢。我已经将代码粘贴在http://pastebin.com/WyKPBhwm上。感谢所有的帮助。 - Favolas
显示剩余4条评论

3
在onConfigurationChanged方法中执行setContentView操作时,ListView会被重新创建。因此,您需要再次将数据加载到ListView中。如果您将ListView绑定到了适配器上,那么您需要在onConfigurationChanged方法中重新绑定它。请注意,不要删除HTML标签。

根据您的评论,您需要将cursorAdapter保存为类成员,这样它就可以在onConfigurationChanged中绑定。 - Sameer
做了那个,但什么也没发生。发现了一件奇怪的事情。在 public void onConfigurationChanged(Configuration newConfig) 中输入了 System.out.println("enter here"); ,但它没有在 logcat 上打印出来。 - Favolas
1
看起来你的android:configChanges设置没有生效。你能同时发布Manifest.xml吗? - Sameer
2
找到问题了。您需要在清单文件中的configChanges设置中添加“|screenSize”。https://dev59.com/AW035IYBdhLWcg3wGMLa - Sameer
1
我相信您无法保存ListView对象本身。当配置更改后,setContentView完成时,ListView将被重新创建。但是当您将ListView绑定到先前执行的查询的光标时,您应该可以看到之前看到的所有行。 - Sameer
显示剩余3条评论

2

您必须重写 onSaveInstanceStateonRestoreInstanceState 方法。

onSaveInstanceState 方法中,将 ListView 列表保存到 Bundle 中。

onRestoreInstanceState 方法中,使用 Bundle 恢复列表并重新创建适配器。

private ArrayList<String> data;

@Override
protected void onSaveInstanceState(Bundle outState) {
    outState.putSerializable("d", data);
    super.onSaveInstanceState(outState);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    if (savedInstanceState != null) {
        data = (ArrayList<String>) savedInstanceState.getSerializable("d");
        ListViewAdapter adapter = new ListViewAdapter(this, data);
        ListView listView = (ListView) findViewById(R.id.layout_listview);
        listView.setAdapter(adapter);
    }
    super.onRestoreInstanceState(savedInstanceState);
}

-1

当进行方向改变时(如果不保存),您将需要重新执行查询,因为这会再次调用onCreate函数。

您可以尝试将列表视图中的数据存储在诸如共享首选项之类的东西中。


谢谢,但是为什么在这种情况下我必须这样做,在AtoZ类中几乎是相同的事情,我不需要吗? - Favolas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接