Android:屏幕旋转后,notifyDataSetChanged()无法更新listview

6
我有一个比较复杂的问题,希望这里有人能帮助我。
在点击事件中,我创建了一个线程,并基于此方法开始了长时间运行的操作。完成长时间运行任务后,它会回调另一个方法,该方法会向处理程序进行发布。具体方法请参考这里
@Override
public void contentSearchModelChanged(Model_ContentSearch csm, ArrayList<Class_Reminder> newRemindersList) {
    remindersList = newRemindersList;
    mHandler.post(mUpdateDisplayRunnable);
}

调用一个Runnable:

// post this to the Handler when the background thread completes
private final Runnable mUpdateDisplayRunnable = new Runnable() {
  public void run() {
    updateDisplay();
  }
};

最后,这是我的updateDisplay()方法所做的事情:
private void updateDisplay() {
    if (csModel.getState() != Model_ContentSearch.State.RUNNING) {
        if(remindersList != null && remindersList.size() > 0){
                r_adapter = new ReminderAdapater(Activity_ContentSearch.this, remindersList, thisListView);
                thisListView.setAdapter(r_adapter);
                r_adapter.notifyDataSetChanged();
        }
    }
}

通常情况下,我这样做时效果非常好。然而,如果我在长时间运行的操作期间更改方向,则不起作用。它确实正确地进行了回调,并且remindersList中确实有项目。但是当它到达这一行时:

r_adapter.notifyDataSetChanged();

什么也没有发生。奇怪的是,如果我再次提交并运行整个过程(不改变方向),它实际上会更新视图两次,一次为上一次提交的结果,然后一秒钟后再次更新为下一次提交的结果。所以适配器确实获得了数据,只是没有刷新视图。

我知道这与方向变化有关,但我无法想出原因。有人可以帮忙吗?或者,有人可以建议处理方向更改的替代方法吗?

巴拉

2个回答

6
问题在于当您更改方向时,新的活动会从头开始(onCreate)。您的长时间运行的进程具有对旧活动(不再可见)的处理方式。您正在正确更新旧活动,但由于它不再显示在屏幕上,因此您看不到它。
这不是一个容易解决的问题。有一个库可以帮助您解决这个问题。它叫做DroidFu。以下是一篇博客文章,比我更准确地描述了您所看到的根本原因以及DroidFu库如何解决它:http://brainflush.wordpress.com/2009/11/16/introducing-droid-fu-for-android-betteractivity-betterservice-and-betterasynctask/ 编辑:(添加用于跟踪活动活动的代码)
在您的应用程序类中添加以下内容:
private Activity _activeActivity;
public void setActiveActivity(Activity activity) {
    _activeActivity = activity;
}
public Activity getActiveActivity() {
    return _activeActivity;
}

在您的活动中,添加以下内容:
@Override
public void onResume() {
    super.onResume();
    ((MyApplicationClassName)getApplication()).setActiveActivity(this);
}

现在你可以通过调用MyApplicationClassName.getActiveActivity()来获取活动的活动。
这不是DroidFu的做法。DroidFu在onCreate中设置活动活动,但我觉得这不是很健壮。

嗯...这似乎非常有帮助,但是似乎没有太多的文档?我不想因为使用DroidFu而不知道如何解决问题而改变我的实现方式,因为它不是“典型”的做法。 - Bara
是的,它看起来像是一个旧的废弃图书馆,但前提似乎是正确的。您可以不使用该库来完成此操作。基本上,Application对象使用onResume跟踪活动Activity。然后,当您准备通知适配器时,从应用程序获取活动Activity,检查它是否为您预期的activity的实例,如果是,则进行类型转换并通知。 - Jere.Jones
追踪“活动 Activity”代码是什么?也就是说,我应该像这样做:CurrentActivity act = new CurrentActivity(); 然后将act传递给Application类吗? - Bara

1

我曾经有过类似的问题,一个耗时的线程通过handler发送了sendEmptyMessage消息,这个handler进而调用了ListAdapter的notifyDataSetChanged方法。这个方法在改变屏幕方向后就无法正常工作。

为了解决这个问题,我在UI线程中声明了第二个handler,然后让第一个handler将sendEmptyMessage消息发送到这个handler,这个handler再调用ListAdapter的notifyDataSetChanged方法。同时还需要将ListAdapter声明为static类型。

我是个新手,不知道这是否是一个丑陋的解决方案,但对我来说它有效...

从Jere.Jones的描述中可以推断出,这个长时间运行的进程向旧Activity的handle发送了sendEmptyMessage消息,然后该handle又向新Activity的handle发送了sendEmptyMessage消息。


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