Android ListView notifyDataSetChanged () из службы

У меня есть фоновый сервис, который получает сообщения с сервера и с этим сообщением обновляет внутренние свойства объектов, которые отображаются в ListView.

Я всегда использую метод runOnUiThread для запуска команды listArrayAdapter.notifyOnDataSetChanged ().

По какой-то причине иногда ListView обновляется, и он показывает мне обновление свойств, а иногда и нет.

Для тестирования я добавил кнопку «Обновить» в свой список ListView, и когда она нажата, выполняется listArrayAdapter.notifyOnDataSetChanged ().

Каждый щелчок на кнопке, просмотр прекрасно обновляется.

Я не могу понять, почему при попытке обновления из службы он не всегда работает, но я думаю, что, возможно, не всегда работает на UIThread …

Я действительно безнадежен и рад помочь.

Мой код

ServerConnectionManager.java – расширяет службу

//example of a command executed when a specific message received from the server: //app is the Application variable public void unFriend(int userId) { serverResponseManager.onUnFriend(app.getApplicationFriend(userId),false); } 

ServerResponseManager.java – класс, который обрабатывает все ответы приложений на сообщения сервера:

  public void onUnFriend(FacebookUser facebookUser, boolean isYouRemovedClient) { //this is the property which will effect the ListView view when calling the //arrayListAdataper.notifyOnDataSetChanged(); facebookUser.setApplicationFriend(false); app.getApplicationFriends().remove(facebookUser); app.getDatabaseManager().deleteApplicationFriend(facebookUser.getId()); //if the application is currently running in the UI (not on the background) it will run a method inside the BaseActivity if (app.isApplicationInForeground()) { app.getCurrentActivity().onUnFriend(facebookUser); if (isYouRemovedClient) app.showToast(facebookUser.getName() + " has removed from your friends", true); else app.showToast(facebookUser.getName() + " has removed you from friends", true); } } 

BaseActivity.java – действие, которое устанавливает всю конфигурацию по умолчанию для всех видов деятельности, которые ее расширяют

 //in this exemple the BaseActivity method does nothing but the ListViewActivity.java method override it public void onUnFriend(FacebookUser facebookUser) { } 

ListViewActivity.java – расширяет BaseActivity и имеет ListView в нем, который должен отражать изменение свойства объекта FacebookUser, которое делается в public void onUnFriend (FacebookUser facebookUser, boolean isYouRemovedClient) в ServerResponseManager.

 @Override public void onUnFriend(FacebookUser facebookUser) { updateView(); } private void updateView() { runOnUiThread(updateViewRunnable()); } private Runnable updateViewRunnable() { Runnable run = new Runnable() { @Override public void run() { listArrayAdapter.notifyDataSetChanged(); } }; return run; } 

Не смешивайте бизнес-логику. Он выглядит настолько сложным, что его трудно читать.

  1. В вашем сервисе транслируйте намерение с информацией об обновлении.
  2. В Activity где ListView , создайте и зарегистрируйте BroadcastReceiver с IntentFilter для ваших событий обновления.
  3. В методе onReceive вашего события обновления BroadcastReceiver обрабатываются, например, список обновлений.

Служба, как правило, не зависит от требований пользовательского интерфейса. Отличный способ разделить службы и связанные с UI вещи – это шаблон шины событий. Для Android откройте https://github.com/greenrobot/EventBus .

В ServerConnectionManager вы можете отправить событие:

 EventBus.getDefault().post(new UnfriendEvent(userId)); 

Теперь зарегистрируйте свою активность на шине событий, и событие будет доставлено в действие, вызвав метод onEvent:

 public void onEventMainThread(UnfriendEvent event) {...} 

Таким образом, вы отключаете свои компоненты, что приводит к аккуратной и чистой разработке программного обеспечения, что очень гибко для изменений.

Вы можете использовать курсор в своем ListView для отображения ваших данных. Служба записывает / обновляет данные в ContentProvider. В конце транзакции базы данных вы просто используете:

 getContext().getContentResolver().notifyChange(PROVIDER_URI,null); 

И ваш ListView автоматически обновляется.

Вместо этого используйте

NotifyDataSetChanged on onDestroy of service.

Просмотр списка будет обновлен

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

Разработка приложения с фоновым сервисом

Он показывает, как получать уведомления от службы и обновлять пользовательский интерфейс.

RunOnUiThread в основном используется перед вызовами AsyncTask. Я думаю, вы должны использовать обработчик вместо этого (он обновляет пользовательский интерфейс и позволяет запустить поток). Попробуйте использовать обработчик и посмотрите, что произойдет