내 어댑터를 업데이트하기 ASyncTask
를 호출하고있어, 한 번 한 동안 나는 내 목록java.lang.IllegalStateException 오류
E/AndroidRuntime (16197)를 채우는 것이 런타임 오류를 받고 있어요 : java.lang.IllegalStateException : 어댑터의 내용이 변경되었지만 ListView가 알림을받지 못했습니다. 어댑터의 내용이 백그라운드 스레드에서 수정되지 않고 UI 스레드에서만 수정되었는지 확인하십시오.
오류 메시지에서 암시하는 것처럼 내 어댑터를 백그라운드 스레드에서 채우는 것은 좋지 않은 생각입니까?
나는 onPostExecute()
에서 notifyDataSetChanged()
을 호출하지만, 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();
}
}
백그라운드 스레드에서 직접 '어댑터'를 업데이트하는 대신 (중간) 결과를 UI 스레드로 보내고 그 결과를 어댑터에 추가하십시오. 두 함수 모두 UI 스레드에서 호출되기 때문에'onProgressUpdate()'또는'onPostExecute()'가 수행합니다. –
원본 게시물에 내 AsyncTask 코드를 추가했습니다. Adapter를 업데이트함으로써 myList.add()를 doInBackground()에서 onProgressUpdate() 또는 onPostExecute()로 이동한다는 의미입니까? 그렇다면 두 개의 변수 (정수 및 항목)를 두 메서드에 전달하는 방법은 무엇입니까? – user1118764
네, 맞습니다. 메서드에 여러 값을 전달하려면 간단한 객체로 묶어야합니다 (예 :'Tuple '). 또는 AsyncTask 기간 동안 임시 목록을 할당하고 백그라운드 스레드의 항목을 추가 한 다음 UI 스레드의 어댑터로 가져 와서 추가 할 수 있습니다. 이는 생산자 - 소비자 패턴과 유사 할 수 있지만 콜백이 동시에 발생하지 않으므로 훨씬 간단합니다. –