Адаптер содержимого и асинхронные обратные вызовы

Я использую стороннюю облачную службу (Kinvey) для получения данных для своего приложения. Все обслуживаемые методы Kinvey заключены в асинхронные классы. В настоящее время я получаю журнал ошибок ниже, и я понимаю, почему я его получаю. Я просто не знаю, как решить проблему.

Ошибка:

03-12 13:41:03.449: E/AndroidRuntime(18375): FATAL EXCEPTION: main

03-12 13:41:03.449: E/AndroidRuntime(18375): 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. [in ListView(2130968661, class android.widget.ListView) with Adapter(class com.example.chartviewer.LazyAdapter)]


Вот фрагмент моего кода, в котором я уведомляю свой адаптер после удаления содержимого в асинхронном методе:

mKinveyClient.appData("artistdata", ArtistData.class).delete(artistID, new KinveyDeleteCallback() {

       @Override
        public void onSuccess(KinveyDeleteResponse result) {

              Log.e("DELEET", "Data Deleted sucessfully");
              Toast.makeText(getBaseContext(),
                      "Artist Deleted", Toast.LENGTH_SHORT).show();

                //refreshes list 
            adapter.notifyDataSetChanged(); 

           //displays dialog box if no artists left 
           displayNoArtist();

        }
        @Override
        public void onFailure(Throwable error) {
             Log.e("DELETE", "AppData.delete Failure", error);
        }
    });


Обновление адаптера:

mKinveyClient.appData("artistdata", ArtistData.class).get(myQuery, new 
KinveyListCallback<ArtistData>() {
         @Override
         public void onSuccess(ArtistData[] result) {

              Log.e("FETCHING", "Data fetched sucessfully");
             for (ArtistData data : result) {


                 String name= data.getArtistname();
                 String imageurl = data.getArtisturl();

                 String id = data.getArtistid();

                 artistIds.add(id);

                  HashMap<String, String> hashMap = new HashMap<String, String>();

                  hashMap.put(TAG_NAME, name);
                  hashMap.put(TAG_IMAGEURL, imageurl);

                  addMyArtists(hashMap);


             }

             displayData();

         }

         @Override
         public void onFailure(Throwable error) {

             Log.e("FETCHING", "AppData.get by Query Failure", error);

         }
     });


Код создателя адаптера:

      list = (ListView)findViewById(R.id.artistlist);
      adapter = new LazyAdapter(MyArtistsActivity.this,"artists", artistItemList);
      list.setAdapter(adapter);
      registerForContextMenu(list);

person AndroidEnthusiast    schedule 12.03.2013    source источник
comment
действительно зависит от того, откуда вы вызываете обновление в AsyncTack. Вы звоните из метода onPostExecute или метода doInBackground? Обновления пользовательского интерфейса всегда следует вызывать с помощью метода onPostExecute.   -  person Phil H    schedule 12.03.2013
comment
??? Никогда не пользовался Кинви. Где вы на самом деле обновляете содержимое адаптера?   -  person G. Blake Meike    schedule 12.03.2013
comment
Код @G.BlakeMeike добавлен выше   -  person AndroidEnthusiast    schedule 12.03.2013
comment
Я инженер в Kinvey. Методы удаления appData.get и appData заключены в AsyncTask, а обратные вызовы onSuccess и onFailure вызываются в методе onPostExecute. @AndroidEnthusiast - можете ли вы опубликовать свой код создания адаптера?   -  person mjsalinger    schedule 12.03.2013
comment
Кроме того, у вас проблемы как с удалением, так и с обновлением, или только с удалением?   -  person mjsalinger    schedule 12.03.2013
comment
@mjsalinger Я заметил, что проблема со списком возникла, когда я удалил элемент и сразу же коснулся экрана. Я решил это, используя диалоговое окно прогресса, когда элемент удален.   -  person AndroidEnthusiast    schedule 12.03.2013
comment
@mjsalinger я думаю, что проблема все еще может существовать, хотя и без диалогового окна, поэтому я включил код создания моего адаптера выше.   -  person AndroidEnthusiast    schedule 12.03.2013


Ответы (1)


Отказ от ответственности: я являюсь членом инженерной группы Kinvey.

Проблема в том, что вы удаляете из artistItemList до удаления из бэкэнда Kinvey, а затем не вызываете adapter.notifyDatasetChanged до обратного вызова. Это приводит к задержке, которую вы заметили, когда базовый набор данных изменился во время ожидания обратного вызова от внутреннего вызова удаления Kinvey. Вам нужно сгруппировать оба этих вызова вместе и сделать это одним из двух способов:

  1. Сделайте идентификатор artistID, который вы передаете методу удаления, окончательным, а в onSuccess удалите элемент из artistItemList перед вызовом adapter.notifyDatasetChanged.
  2. Вызовите adapter.notifyDatasetChanged перед вызовом метода kinveyClient.appData().delete() сразу после удаления элемента из artistItemList. Этот параметр может вызвать проблемы, если удаление не удается на серверной части Kinvey.
person mjsalinger    schedule 12.03.2013