簡體   English   中英

java.lang.IllegalStateException錯誤

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM