Android:notifyDataSetChanged() 在方向改变后不更新列表视图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3081778/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android: notifyDataSetChanged() not updating listview after orientation change
提问by Bara
I have a semi-complicated problem and hoping that someone here will be able to help me.
我有一个半复杂的问题,希望这里有人能够帮助我。
On a click event I create a thread and start a long-running operation based on thismethod. After the long-running task is completed, it does a callback to another method, which does a post to the handler:
在单击事件上,我创建一个线程并基于此方法启动一个长时间运行的操作。长时间运行的任务完成后,它会回调另一个方法,该方法会向处理程序发送消息:
@Override
public void contentSearchModelChanged(Model_ContentSearch csm, ArrayList<Class_Reminder> newRemindersList) {
remindersList = newRemindersList;
mHandler.post(mUpdateDisplayRunnable);
}
Which calls a Runnable:
其中调用一个 Runnable:
// post this to the Handler when the background thread completes
private final Runnable mUpdateDisplayRunnable = new Runnable() {
public void run() {
updateDisplay();
}
};
Finally, here is what my updateDisplay() method is doing:
最后,这是我的 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();
}
}
}
This works beautifully when I do this normally. However, if I change the orientation while the long-running operation is running, it doesn't work. It does make the callback properly, and the remindersList does have items in it. But when it gets to this line:
当我正常执行此操作时,这非常有效。但是,如果我在长时间运行的操作运行时更改方向,它将不起作用。它确实使回调正确,并且提醒列表中确实有项目。但是当它到达这一行时:
r_adapter.notifyDataSetChanged();
Nothing happens. The odd thing is, if I do another submit and have it run the whole process again (without changing orientation), it actually updates the view twice, once for the previous submit and again for the next. So the view updates once with the results of the first submit, then again with the results of the second submit a second later. So the adapater DID get the data, it just isn't refreshing the view.
没发生什么事。奇怪的是,如果我再次提交并让它再次运行整个过程(不改变方向),它实际上会更新视图两次,一次用于前一次提交,一次用于下一次。因此,视图会使用第一次提交的结果更新一次,然后再使用第二次提交的结果进行更新。所以适配器确实获得了数据,它只是没有刷新视图。
I know this has something to do with the orientation change, but I can't for the life of me figure out why. Can anyone help? Or, can anyone suggest an alternative method of handling threads with orientation changes?
我知道这与方向变化有关,但我终生无法弄清楚原因。任何人都可以帮忙吗?或者,有人可以建议另一种处理方向变化的线程的方法吗?
Bara
巴拉
采纳答案by Jere.Jones
The problem is that when you change orientations a new activity is spun up from the beginning (onCreate). Your long running process has a handle to the old (no longer visible) activity. You are properly updating the old activity but since it isn't on screen anymore, you don't see it.
问题在于,当您更改方向时,会从一开始就启动一个新活动 (onCreate)。您长时间运行的进程具有处理旧(不再可见)活动的句柄。您正在正确更新旧活动,但由于它不再出现在屏幕上,因此您看不到它。
This is not an easy problem to fix. There is a library out there that may help you though. It is called DroidFu. Here is a blog post that (much more accurately than I) describes the root cause of what you are seeing and how the DroidFu library combats it: http://brainflush.wordpress.com/2009/11/16/introducing-droid-fu-for-android-betteractivity-betterservice-and-betterasynctask/
这不是一个容易解决的问题。那里有一个图书馆可以帮助你。它被称为 DroidFu。这是一篇博客文章(比我更准确)描述了您所看到的根本原因以及 DroidFu 库如何与之对抗:http://brainflush.wordpress.com/2009/11/16/introducing-droid- fu-for-android-betteractivity-betterservice-and-betterasynctask/
Edit: (Adding code for tracking active activity)
编辑:(添加用于跟踪活动活动的代码)
In your application class add this:
在您的应用程序类中添加:
private Activity _activeActivity;
public void setActiveActivity(Activity activity) {
_activeActivity = activity;
}
public Activity getActiveActivity() {
return _activeActivity;
}
In your Activities, add this:
在您的活动中,添加以下内容:
@Override
public void onResume() {
super.onResume();
((MyApplicationClassName)getApplication()).setActiveActivity(this);
}
Now you can get the active activity by calling MyApplicationClassName.getActiveActivity();
现在您可以通过调用 MyApplicationClassName.getActiveActivity(); 来获取活动活动;
This is not how DroidFu does it. DroidFu sets the active activity in onCreate but I don't feel that is very robust.
这不是 DroidFu 的做法。DroidFu 在 onCreate 中设置活动活动,但我觉得这不是很健壮。
回答by Arne
I had a similar problem, having a time consuming thread sendEmptyMessage to a handler, which in turn called notifyDataSetChanged on a ListAdapter. It worked fine until I changed orientation.
我有一个类似的问题,有一个耗时的线程 sendEmptyMessage 到一个处理程序,它又在 ListAdapter 上调用 notifyDataSetChanged 。它工作正常,直到我改变方向。
I solved it by declaring a second handler in the UI thread and make the first handler sendEmptyMessage to this handler, which in turn called notifyDataSetChanged on the ListAdapter. And having the ListAdapter declared as static.
我通过在 UI 线程中声明第二个处理程序并将第一个处理程序 sendEmptyMessage 发送到此处理程序来解决它,该处理程序又在 ListAdapter 上调用 notifyDataSetChanged。并将 ListAdapter 声明为静态。
I'm a newbie so I don't know if it is an ugly solution, but it worked for me...
我是新手,所以我不知道这是否是一个丑陋的解决方案,但它对我有用......
From Jere.Jones description I would assume this works as: The long running process sendEmptyMessage to the handle from the old Activity, which in turn sendEmptyMessage to the handle in the new Activity.
从 Jere.Jones 的描述来看,我认为它的工作原理是:长时间运行的进程将 sendEmptyMessage 发送到旧活动的句柄,然后将 sendEmptyMessage 发送到新活动中的句柄。