Android:notifyDataSetChanged()在方向更改后不更新listview

时间:2010-06-21 02:18:47

标签: android listview multithreading orientation android-arrayadapter

我有一个半复杂的问题,并希望有人能够帮助我。

在click事件中,我创建一个线程并根据this方法启动长时间运行的操作。在长时间运行的任务完成后,它会对另一个方法进行回调,该方法会向处理程序发送一个帖子:

@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();

什么都没发生。奇怪的是,如果我再做一次提交并让它再次运行整个过程(不改变方向),它实际上会更新视图两次,一次用于上一次提交,另一次用于下一次提交。因此,视图会使用第一次提交的结果更新一次,然后再次使用第二次提交的结果更新一次。因此,适应器DID获取数据,它只是没有刷新视图。

我知道这与方向改变有关,但我不能为我的生活找出原因。有人可以帮忙吗?或者,任何人都可以建议一种处理方向更改线程的替代方法吗?

巴拉

2 个答案:

答案 0 :(得分: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中设置了活动活动,但我觉得它不是很强大。

答案 1 :(得分:1)

我有一个类似的问题,有一个耗时的线程sendEmptyMessage给一个处理程序,后者又在ListAdapter上调用notifyDataSetChanged。它工作正常,直到我改变方向。

我通过在UI线程中声明第二个处理程序并将第一个处理程序sendEmptyMessage发送到此处理程序来解决它,该处理程序又在ListAdapter上调用notifyDataSetChanged。并将ListAdapter声明为静态。

我是新手,所以我不知道这是不是一个丑陋的解决方案,但它对我有用......

从Jere.Jones描述我将假设它的工作原理如下:长时间运行的进程sendEmptyMessage来自旧Activity的句柄,而旧的Activity又将sendEmptyMessage发送到新Activity中的句柄。