[英]java.lang.IllegalStateException error
我正在調用ASyncTask
來更新我的適配器, ASyncTask
我會在填充列表時收到此運行時錯誤
E / AndroidRuntime(16197):java.lang.IllegalStateException:適配器的內容已更改,但ListView沒有收到通知。 確保不從后台線程修改適配器的內容,而僅從UI線程修改。
像錯誤消息所暗示的那樣,從后台線程填充適配器是一個壞主意嗎?
我打電話notifyDataSetChanged()
在onPostExecute()
但我也得到了同樣的錯誤,當我把它在onProgressUpdate()
這是我的ASyncTask。 假設fetchOneItem()從項目列表中提取單個項目,填寫名稱/描述,然后在下一次迭代中移至下一個項目。
private class GetItems extends AsyncTask<Integer, Integer, Integer> {
@Override
protected void onPreExecute() {
super.onPreExecute();
pd = new ProgressDialog(context);
pd.setTitle("Displaying...");
pd.setMessage("Please wait.");
pd.setCancelable(false);
pd.setIndeterminate(true);
pd.show();
TextView myMsg = (TextView)findViewById(R.id.topMsg);
myMsg.setText("Displaying items...");
}
protected Integer doInBackground(Integer... params) {
// TODO Auto-generated method stub
do {
fetchOneItem(); // fetches 1 item
myList.add(new Item(name, description));
Log.i(TAG, "Adding " + name + ", " + desc + ", adapter size = " + myAdapter.getCount());
publishProgress(i);
} while (doneFetching != true);
Log.i(TAG, "Completed loading, i =" + i);
return i;
}
protected void onProgressUpdate(Integer... values) {
TextView myMsg = (TextView)findViewById(R.id.topMsg);
myMsg.setText("Displaying " + Integer.toString(values[0].intValue()) + " items");
}
@Override
protected void onPostExecute(Integer numItems) {
TextView myMsg = (TextView)findViewById(R.id.topMsg);
myMsg.setText("Displayed " + numItems + " items");
myAdapter.notifyDataSetChanged();
allItemsLoaded = true;
Log.i(TAG, "Adapter size = " + myAdapter.getCount());
pd.dismiss();
}
}
如我所見,您正在嘗試“實時”更新列表視圖,對嗎?
好吧,我不知道該怎么做,所以我建議您實現一個刷新按鈕來調用此AsyncTask。 如果要向用戶顯示您實際上正在更新列表視圖,則發送DialogProgress很重要。 希望能幫助到你!
是的,您可以看到android不允許您執行此操作。 如果要更新任何視圖,則應在UI線程中進行。 但是,您也永遠不要在UI線程中使用慢速操作,例如android不允許的網絡通信。 實際上,您應該使UI代碼盡可能短,因為如果花費的時間太長,那么android會認為您的應用已崩潰。
編輯:我認為您正在使用ArrayAdapter,它將在您更新它時通知更改。
因此,您有兩種選擇:
使用ArrayAdapter,但在UI線程中對其進行更新。
或實現您自己的BaseAdapter子類,然后您做對了。
ArrayAdapter適用於簡單情況,通常帶有靜態數據集。
發帖晚,但可能會幫助遇到類似情況的人。
問題:您的運行時間很長,並且希望將其帶入后台線程。 同樣,在操作完成之后,您想更新UI線程上的視圖。
解:
//spawn a new thread for background processing.
new Thread(new Runnable() {
@Override
public void run() {
//starting your background operation.
//this is a network call.
final Location location = BackendApi.builder().getSlaveLocation(mActivity.getApplicationContext(), "xyz", null);
//now i want to update views on UI thread.
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
//this code will run on UI thread.
myView.setText("Latitude: " + location.getLatitude());
}
});
}
}).start();
在更新視圖/適配器之前,請確保未破壞活動。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.