Android - notifyDataSetChanged()和线程

时间:2014-06-22 03:18:48

标签: android android-asynctask android-ui android-adapter

我有一个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的初学者,对这些基本问题的任何帮助都将非常感激。我的互联网搜索没有给我我想要的答案。也非常感谢你的时间。

2 个答案:

答案 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()的方法   在工作线程上?

实际上,有几个。您可以使用HandlerAsyncTask.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
        }
    });