LiveData 未将数据从一个 Activity 更新到另一个 Activity - Android

LiveData not updating data from one Activity to another Activity - Android

我有2个Activity

  1. 列表Activity
  2. 详情Activity

列表 Activity 显示项目列表,单击列表中的项目显示详细信息 Activity。 在 ListActivity 中,我们观察从数据库中获取提要,一旦完成,我们就会更新 UI.

列表页

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
    }

}

为简单起见,一些代码已被抽象化。如果需要,我可以添加它们来追踪问题

经过大量调查和 从另一个问题中得出的一些想法。我想通了这个问题。

问题

DatabaseCreator(application).database.feedDao() 没有创建数据库的单例实例,因此第一个 Activity 有另一个实例,其中 LiveData 正在侦听更改,第二个 Activity 有更新数据后回调被忽略的另一个实例。

解决方案

使用 Dagger 或任何其他依赖注入来确保只创建 DB 和 DAO 的单个实例。

我在同一实体的多个活动中遇到了同样的问题。对我来说,将 Room Database 实例编码为 Singleton 很有用,例如:this (step 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 中(class 从 AndroidViewModel 扩展了 Context 参数):

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

现在,就我而言,每次我在配置活动中编辑一个值时,它都会反映在其他活动中。

希望对您有所帮助。

我遇到了同样的问题。在下面的代码中,我忘记了一行并且单例没有工作(问题与主要答案中的问题相同)。

@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