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

时间:2015-03-04 15:39:33

标签: android android-asynctask

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

我想通过AsyncTask将listview更新为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$3.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$1.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$2.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

1 个答案:

答案 0 :(得分:1)

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

另一方面,

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

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

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