2013-11-11 4 views
0

Имейте такую ​​ошибку, при попытке обновить ListView в моем фрагменте из AsyncTask:Update ListView с помощью AsyncTask

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. 

Мой AsyncTask класс

protected Void doInBackground(Void... params) { 
     int nextStep; 
     BaseAnt tempAnt = null; 
     ArrayList<BaseAnt> antList = new ArrayList<BaseAnt>(); 
     while (true) { 
      Log.d("myLogs", "Start from APP"); 
      nextStep = RandomNumber.getRandomNumber(3); 
      switch (nextStep) { 
      case 0: 
       tempAnt = new GuardAnt(); 
       AppStat.addToLog("Guard"); 
       break; 
      case 1: 
       tempAnt = new MotherAnt(); 
       AppStat.addToLog("Mother born"); 
       break; 
      case 2: 
       tempAnt = new WorkerAnt(); 
       AppStat.addToLog("Worker born"); 
       break; 
      default: 
       break; 
      } 
      antList.add(tempAnt); 
      try { 
       TimeUnit.SECONDS.sleep(1); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
      for (int i = 0; i < antList.size(); i++) 
       antList.get(i).eat(); 
      publishProgress(String.valueOf(AppStat.WATER)); 
      if (AppStat.WATER < 0) 
       break; 
     } 
     return null; 

    } 

    protected void onPostExecute(String result) { 

    } 

    @Override 
    protected void onProgressUpdate(String... values) { 
     Log.d("myLogs", "onProgressUpdate"); 
     LogFragment.mLogAdapter.notifyDataSetChanged(); 
     LogFragment.mLogAdapter.setSelectToLast(); 
     StatFragment.tvWater.setText(String.valueOf(AppStat.WATER)); 
     super.onProgressUpdate(values); 
    } 

AppStat это класс расширяет приложение, что cointain информацию о переменных я нужен и способ

public static void addToLog(String str) { 
    if (listLog.size() > 256) 
     listLog.remove(0); 
    listLog.add(getNowtime() + ": " + str); 
} 

В LogAdapter простирается BaseAdapter:

public void setSelectToLast() { 
    Log.d("myLogs","UpdateToLast"); 
    notifyDataSetChanged(); 
    LogFragment.lvList.setSelection(getCount() + 1); 
} 

Как это исправить?

ответ

2

Вы не должны вызывать addToLog() (или любой другой операции UI) в doInBackground(). Либо вы собираете все в doInBackground, вернуть его в результате, а затем обновить список в onPostExecute, или вы используете publishProgress() и изменить содержимое списка в onProgressUpdate() ...

onPostExecute и onProgressUpdate выполняются в UI thread, doInBackground выполняется в другой теме.

+0

Что делать, если моя асинтеза должна работать долгое время (я создаю симулятор семейства муравьев) OnPostExecute, поскольку я думаю, что вызов будет только тогда, когда работа с асинтексом будет работать? – Sunstrike

+0

Да, в этом случае вы должны использовать publishProgress. Данные, которые вы передаете, будут доступны в onProgressUpdate – jpm

+0

Посмотрите на образец: http://developer.android.com/reference/android/os/AsyncTask.html – jpm

0

Вы должны запустить обновление в основном потоке, используя что-то вроде этого:

MainActivity.this.runOnUiThread(new runnable(){ 
public void run(){ 
    Log.d("UI thread", "I am the UI thread"); 
} 

});

вы можете проверить этот пост также: Android basics: running code in the UI thread

0

Попробуйте использовать

MainActivity.this.runOnUiThread(new runnable() 
{ 
    public void run() 
    { 
    LogFragment.mLogAdapter.notifyDataSetChanged(); 
    LogFragment.mLogAdapter.setSelectToLast(); 
    StatFragment.tvWater.setText(String.valueOf(AppStat.WATER)); 
    } 
} 

в методе onProgressUpdate

+1

onProgressUpdate выполнен в mainthread. поэтому нет необходимости вызывать runOnUiThread – jpm

0

Попробуйте вызвать notifyDataSetChanged() на вашем адаптере в onPostExecute.

+0

адаптер не имеет onpostexecute = O – Sunstrike

1

Обновления Ui сделаны из метода onpostexecute() в асинтете. Сделайте это, и он будет работать нормально, поскольку onpostexecute работает по потоку ui после того, как doinbackground() завершил свою работу.

Смежные вопросы