Android - 在AsyncTask中创建ListView内容会导致随机崩溃

时间:2014-12-13 12:21:09

标签: android android-listview android-asynctask android-adapter

我在后台创建ListView的内容,当添加每个项目时,我更新ListView适配器。通常它工作正常,但有时我得到这个错误。奇怪的是,它在我的Galaxy s4 mini中比在我的HTC Sensation中发生的次数多10倍。我不明白为什么会发生这种情况,因为我通过UI线程清楚地通知适配器。有什么想法吗?

java.lang.IllegalStateException: The content of the adapter has changed but ListView 
did not receive a notification. Make sure the content of your adapter is not modified 
from a background thread, but only from the UI thread. Make sure your adapter calls 
notifyDataSetChanged() when its content changes. [in ListView(2131100779, class 
util.TouchInterceptor) with Adapter(class com.bill.deuterh.ListActivity$ListAdapter)]

的AsyncTask:

private class AsyncCaller extends AsyncTask<Void,Void,Void>{

    @Override
    protected void onPostExecute(Void result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        ListActivity.this.runOnUiThread(new Runnable(){
            @Override
            public void run() {
                findViewById(R.id.progress_bar).setVisibility(View.GONE);
            }
        });
    }

    @Override
    protected Void doInBackground(Void... params) {
        // TODO Auto-generated method stub

        for (int i=0;i<table.length;i++){
            if(isCancelled()){break;}
            myList.add(createObject(table[i])));
            ListActivity.this.runOnUiThread(new Runnable(){
                @Override
                public void run() {
                    ListAdapter.notifyDataSetChanged();
                }
            });
        }

        return null;
    }
}

(如果重要的话,我将Listview转换为TouchInterceptor,这是一个修改过的google类,用于支持通过拖放重新排列listview项目。)

3 个答案:

答案 0 :(得分:0)

这应该只在onpostexecute结束时运行一次而不需要runonuithread。 ListAdapter.notifyDataSetChanged();

删除它:

   ListActivity.this.runOnUiThread(new Runnable(){
        @Override
        public void run() {
            ListAdapter.notifyDataSetChanged();
        }
    });

并把它:

    @Override
    protected void onPostExecute(Void result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        findViewById(R.id.progress_bar).setVisibility(View.GONE);
ListAdapter.notifyDataSetChanged();

    }

答案 1 :(得分:0)

不要在doInBackground(Void... params)中编写与UI相关或更新的任何代码。对于UI上的更新,使用Async的onPostExecute(Void result)方法。 因此,请从doInbackGround(Void... params){}

中删除adatper的通知

答案 2 :(得分:0)

试试这个:如果其他一切都设置正确。然后,此代码将在列表视图中立即显示您doInBackground的所有更新=良好的用户体验!

private class AsyncCaller extends AsyncTask<Void,Void,Void>{

@Override
protected void onPostExecute(Void result) {
    // TODO Auto-generated method stub
    super.onPostExecute(result);
                    findViewById(R.id.progress_bar).setVisibility(View.GONE);
}

@Override
protected Void doInBackground(Void... params) {
    // TODO Auto-generated method stub

    for (int i=0;i<table.length;i++){
        if(isCancelled()){break;}
        myList.add(createObject(table[i])));
        publishProgress();
    }

    return null;
}

protected void onProgressUpdate(Void.. values) {
ListAdapter.notifyDataSetChanged();
}

}

OnPreExecute, onPostExecute and onProgressUpdate已在UIThread上运行。也许你没有以正确的方式执行asynctask。这就是为什么没有数据更新的原因?