ListView 的 onProgressUpdate 方法中的 notifyDataSetChanged() 通过 AsyncTask 更新 listView

notifyDataSetChanged() in onProgressUpdate method for ListView to update the listView by AsyncTask

在我的应用程序中。有一个 ListView 并将数据填充到列表视图中抛出使用 ArrayList 的 ArrayAdapter。

我想通过 AsyncTask 将列表视图更新为 doInBackground 方法,所以我使用 onProgressUpdate 方法。在这里,我在适配器上执行 notifyDataSetChanged。

但是当编译器尝试执行代码时aAdapter.notifyDataSetChanged(); 然后它抛出错误。

代码:-

private class StatisticsTask extends AsyncTask<String, Integer, Long> {

    @Override
    protected Long doInBackground(String... params) {
        int count = 0;

        while(count < dummyClass.getStatisticsClassList().size()){
            try {
                Thread.sleep(1000);
                onProgressUpdate(count);
                count++;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        if (count == dummyClass.getStatisticsClassList().size()) {
            statisticsTask.cancel(true);
        }
        return null;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        updateProgress(values[0]);
    }   
}

public void updateProgress(Integer... values) {
aListStatisticsClass.add(dummyClass.getStatisticsClassList().get(values[0]));
aAdapterStatisticsClass.notifyDataSetChanged();
}   

错误:-

03-04 15:33:49.757: E/AndroidRuntime(1778): FATAL EXCEPTION: AsyncTask #1
03-04 15:33:49.757: E/AndroidRuntime(1778): Process: com.example.elevateapp, PID: 1778
03-04 15:33:49.757: E/AndroidRuntime(1778): java.lang.RuntimeException: An error occured while executing doInBackground()
03-04 15:33:49.757: E/AndroidRuntime(1778):     at android.os.AsyncTask.done(AsyncTask.java:300)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at java.util.concurrent.FutureTask.run(FutureTask.java:242)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:231)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at java.lang.Thread.run(Thread.java:841)
03-04 15:33:49.757: E/AndroidRuntime(1778): Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
03-04 15:33:49.757: E/AndroidRuntime(1778):     at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6024)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:820)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at android.view.View.requestLayout(View.java:16431)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at android.view.View.requestLayout(View.java:16431)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at android.view.View.requestLayout(View.java:16431)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at android.view.View.requestLayout(View.java:16431)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:352)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at android.view.View.requestLayout(View.java:16431)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:352)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at android.view.View.requestLayout(View.java:16431)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at android.widget.AbsListView.requestLayout(AbsListView.java:1916)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at android.widget.AdapterView$AdapterDataSetObserver.onChanged(AdapterView.java:814)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at android.widget.AbsListView$AdapterDataSetObserver.onChanged(AbsListView.java:6287)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at android.database.DataSetObservable.notifyChanged(DataSetObservable.java:37)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at android.widget.BaseAdapter.notifyDataSetChanged(BaseAdapter.java:50)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at android.widget.ArrayAdapter.notifyDataSetChanged(ArrayAdapter.java:286)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at com.example.elevateapp.MainActivity.updateProgress(MainActivity.java:94)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at com.example.elevateapp.MainActivity$StatisticsTask.onProgressUpdate(MainActivity.java:81)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at com.example.elevateapp.MainActivity$StatisticsTask.doInBackground(MainActivity.java:67)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at com.example.elevateapp.MainActivity$StatisticsTask.doInBackground(MainActivity.java:1)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at android.os.AsyncTask.call(AsyncTask.java:288)
03-04 15:33:49.757: E/AndroidRuntime(1778):     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
03-04 15:33:49.757: E/AndroidRuntime(1778):     ... 4 more

notifyDataSetChanged() 以及所有其他 UI 相关的方法必须在主 (UI) 线程上执行。

另一方面,

AsyncTask 创建并 运行 自己的线程,以便消除主线程的压力并让应用程序保持用户响应。

根据 documentationonProgressUpdate(...) 方法是 UI 线程上的 运行,但您应该调用 publishProgress(...) 方法,并且您是直接从导致错误的非 UI 线程调用 onProgressUpdate(...)

要解决此问题,只需将 onProgressUpdate(count) 替换为 publishProgress(count) 即可。干杯 :D