我有一个AsyncTask,可以在doInBackground()
方法中执行一些数字运算(在接下来的几行中有更多细节)。在doInBackground()
中操作的数据是与ListView's
适配器关联的数据(在我的情况下为SimpleAdapter
)。处理适配器数据后,我需要做的是调用notifyDataSetChanged()
并更新我的ListView
。但是在notifyDataSetChanged()
内调用doInBackground()
会显示“不幸”应用名称“已停止工作”消息。我的错误堆栈显示了这个:
06-22 08:01:49.083:E / AndroidRuntime(9955):致命异常:AsyncTask#2 06-22 08:01:49.083:E / AndroidRuntime(9955):java.lang.RuntimeException:执行doInBackground()时发生错误 06-22 08:01:49.083:E / AndroidRuntime(9955):在android.os.AsyncTask $ 3.done(AsyncTask.java:299) 06-22 08:01:49.083:E / AndroidRuntime(9955):at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352) 06-22 08:01:49.083:E / AndroidRuntime(9955):at java.util.concurrent.FutureTask.setException(FutureTask.java:219) 06-22 08:01:49.083:E / AndroidRuntime(9955):at java.util.concurrent.FutureTask.run(FutureTask.java:239) 06-22 08:01:49.083:E / AndroidRuntime(9955):在android.os.AsyncTask $ SerialExecutor $ 1.run(AsyncTask.java:230) 06-22 08:01:49.083:E / AndroidRuntime(9955):at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) 06-22 08:01:49.083:E / AndroidRuntime(9955):at java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:573) 06-22 08:01:49.083:E / AndroidRuntime(9955):at java.lang.Thread.run(Thread.java:838) 06-22 08:01:49.083:E / AndroidRuntime(9955):引起:android.view.ViewRootImpl $ CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触及其视图。
最后一行
06-22 08:01:49.083:E / AndroidRuntime(9955):引起:android.view.ViewRootImpl $ CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触及其视图。
告诉我需要调试的信息。我通过从notifyDataSetChanged()
调用onPostExecute()
解决了这个问题但我仍然不明白该方法实际上是如何工作的。我的问题是:
Q1。 notifyDataSetChanged()
如何实际更新UI?
Q2。 notifyDataSetChanged()
和UI线程之间的联系是什么?
Q3。有没有可以在工作线程上调用notifyDataSetChanged()
的方法?
我是Android的初学者,对这些基本问题的任何帮助都将非常感激。我的互联网搜索没有给我我想要的答案。也非常感谢你的时间。
答案 0 :(得分:8)
Q1。 notifyDataSetChanged()实际上如何更新UI?
实际上,notifyDataSetChanged()
仅在其关联的观察者上触发onChanged()
方法。对于AdapterView
子类(例如ListView
),最终会调用requestLayout()
schedules a layout pass of the view tree。
这意味着ListView
没有"立即"重新创建其子视图,但只要UI线程可以自由处理消息,它就会重新创建。最终,将为每个项目调用getView()
。
Q2。 notifyDataSetChanged()和UI之间的联系是什么 线程?
基本上,不允许从后台线程修改适配器的内容。 notifyDataSetChanged()
只是通知AdapterView
其数据已更改的方式,应该重新绘制。
Q3。有没有可以调用notifyDataSetChanged()的方法 在工作线程上?
实际上,有几个。您可以使用Handler
,AsyncTask.onPostExecute()
,Activity.runOnUiThread()
或View.post()
。
答案 1 :(得分:3)
How does notifyDataSetChanged() actually update the UI ?
它会更改之前添加的ListView项目,从而实际更改您的UI。
示例:当您add/remove
传递给适配器的array
时。
What is the connection between notifyDataSetChanged() and the UI thread ?
当您从UI线程创建视图时,它是唯一可以更新/更改您的视图的线程,如果您尝试从不同的线程更新它,您将收到此错误:CalledFromWrongThreadException
。
Is there any method in which notifyDataSetChanged() can be called on a worker thread ?
是的,您可以调用活动的runOnUiThread
来调用主/ UI线程,以便您更新ListView。
<强>样品:强>
runOnUiThread(new Runnable() {
@Override
public void run() {
//notifyDataSetChanged here or update your UI on different thread
}
});