4

我有 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
    }

}

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

4

3 回答 3

5

经过大量调查并从另一个问题的答案中获得了一些想法。我弄清楚了这个问题。

问题

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

解决方案

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

于 2017-07-21T19:22:59.957 回答
1

我在同一实体的多个活动中面临同样的问题。对我来说,将 Room Database 实例编码为 Singleton 很有用,例如:this(第 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());
}

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

希望这有帮助。

于 2018-01-17T05:01:57.270 回答
0

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

@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
于 2021-07-16T09:16:10.090 回答