LiveData не обновляет данные из одного действия в другое действие - Android

у меня 2 Activity а именно

  1. Список Activity
  2. Деталь Activity

Список Activity показывает список элементов, а деталь Activity отображается при щелчке элемента в списке. В ListActivity мы наблюдаем за получением каналов из БД, и как только мы это делаем, мы обновляем пользовательский интерфейс.

Страница со списком

feedViewModel.getFeeds().observe(this, Observer { feeds ->
      feeds?.apply {
            feedAdapter.swap(feeds)
            feedAdapter.notifyDataSetChanged()
      }
})

Теперь у нас есть страница DetailActivity, которая обновляет ленту (элемент), и Activity завершена, но изменения не отражаются в ListActivity.

Страница сведений

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        feedViewModel.setFeedId(id)
        feedViewModel.updateFeed()
}

Модель представления фида

class FeedViewModel(application: Application) : AndroidViewModel(application) {


    private val feedRepository = FeedRepository(FeedService.create(getToken(getApplication())),
            DatabaseCreator(application).database.feedDao())

    /**
     * Holds the id of the feed
     */
    private val feedId: MutableLiveData<Long> = MutableLiveData()

    /**
     * Complete list of feeds
     */
    private var feeds: LiveData<Resource<List<Feed>>> = MutableLiveData()

    /**
     * Particular feed based upon the live feed id
     */
    private var feed: LiveData<Resource<Feed>>

    init {
        feeds = feedRepository.feeds
        feed = Transformations.switchMap(feedId) { id ->
            feedRepository.getFeed(id)
        }
    }

    /**
     * Get list of feeds
     */
    fun getFeeds() = feeds

    fun setFeedId(id: Long) {
        feedId.value = id
    }

    /**
     * Update the feed
     */
    fun updateFeed() {
        feedRepository.updateFeed()
    }

    /**
     * Get feed based upon the feed id
     */
    fun getFeed(): LiveData<Resource<Feed>> {
        return feed
    }

}

Для простоты некоторый код был абстрагирован. При необходимости могу добавить их для отслеживания проблемы


person Akshay Chordiya    schedule 19.07.2017    source источник


Ответы (3)


После долгих исследований и некоторых идей из этот ответ на другой вопрос. Я понял проблему.

Проблема

DatabaseCreator(application).database.feedDao() не создавал одноэлементный экземпляр базы данных, из-за чего у первого Activity был другой экземпляр, где LiveData прослушивал изменения, а у второго Activity был еще один экземпляр, где после обновления данных обратный вызов был проигнорирован.

Решение

Используйте Dagger или любую другую инъекцию зависимостей, чтобы гарантировать создание только одного экземпляра БД и DAO.

person Akshay Chordiya    schedule 21.07.2017
comment
У меня точно такая же проблема, однако я аннотировал экземпляр БД и DAO как синглтоны. Что вы изменили? Кстати, я использую Dagger 2. Если вам нужна дополнительная информация, вот вопрос, который я разместил: stackoverflow.com/questions/48267724/ - person César Alberca; 16.01.2018

Я столкнулся с этой же проблемой в нескольких действиях для одних и тех же объектов. Мне было полезно кодировать экземпляр базы данных Room как Singleton, например: это шаг 5)

Пример:

public abstract class MyDatabase extends RoomDatabase {
    private static MyDatabase mMyDatabase;
    public static MyDatabase getInstance(Context context) {
        if(mMyDatabase==null){
            mMyDatabase = Room.databaseBuilder(context.getApplicationContext(), MyDatabase.class, "app_database").build();
            return mMyDatabase;
        }
    }
}

И в каждой ViewModel, которая у вас есть (класс расширяется от AndroidViewModel для параметра Context):

    public MyViewModel(@NonNull Application application) {
        super(application);
        mMyDatabase = MyDatabase.getInstance(application.getApplicationContext());
}

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

Надеюсь, это поможет.

person feathersanddown    schedule 17.01.2018

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

@Database(entities = [SleepNight::class], version = 1, exportSchema = false)
abstract class SleepDatabase : RoomDatabase() {

   abstract val sleepDatabaseDao: SleepDatabaseDao

   companion object {

       @Volatile
       private var INSTANCE: SleepDatabase? = null

       fun getInstance(context: Context): SleepDatabase {
           synchronized(this) {
               var instance = INSTANCE

               if (instance == null) {
                   instance = Room.databaseBuilder(
                           context.applicationContext,
                           SleepDatabase::class.java,
                           "sleep_history_database"
                   )
                           .fallbackToDestructiveMigration()
                           .build()
                   INSTANCE = instance
               }
               return instance
           }
       }
   }
}

Забытая строка:

INSTANCE = instance
person Evgeniy Er    schedule 16.07.2021