Android Room:更新插入的LiveData回调?

Lon*_*ger 19 android android-room android-livedata android-architecture-components

我有一个简单的DAO,包括CRUD功能

FeedEntryDAO.java

@Dao
public interface FeedEntryDAO {

  @Query("SELECT * FROM feedEntrys")
  LiveData<List<FeedEntry>> getAll();

  @Query("SELECT * FROM feedEntrys WHERE uid = :uid LIMIT 1")
  LiveData<FeedEntry> findByUid(int uid);

  @Insert
  void insertAll(FeedEntry... feedEntries);

  @Delete
  void delete(FeedEntry feedEntry);

  @Update
  int update(FeedEntry feedEntry);

}
Run Code Online (Sandbox Code Playgroud)

对于select,可以返回LiveData类型.

在Activity中,代码非常适合选择

viewModel.getFeedEntrys().observe(this,entries -> {...});
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试插入,更新,删除数据时.代码看起来有点难看,每次都会创建一个asynctask.

new AsyncTask<FeedEntry, Void, Void>() {
                @Override
                protected Void doInBackground(FeedEntry... feedEntries) {
                  viewModel.update(feedEntries[0]);
                  return null;
                }
}.execute(feedEntry);
Run Code Online (Sandbox Code Playgroud)

我有2个问题:

  1. 我可以使用LiveData来包装删除,插入,更新功能吗?
  2. 更好的方法是为删除,插入,更新维护这样的asynctask类?

感谢任何建议和意见.谢谢.

Ema*_*l S 6

  1. 我可以使用LiveData来包装删除,插入,更新通话吗?

不,你不能.我写了一个答案的问题.原因是,LiveData用于通知更改.插入,更新,删除不会触发更改.它将返回已删除的行,插入的ID或受影响的行.即使它看起来很糟糕也没有意义,没有LiveData包裹你的东西.无论如何,在调用之间使用Single这样的东西是有意义的,让操作在RX-Java操作上触发和操作.

如果要触发这些调用,您会在选择查询上观察,该查询会通知您已更新,插入或删除某些/任何数据的LiveData.

  1. 更好的方法是为删除,插入,更新维护这样的asynctask类?

查看您的示例后,您似乎滥用了(模型/视图/)ViewModel-Pattern.您永远不应该在视图中访问您的存储库.我不确定你是否这样做是因为它在样品中不可见.无论如何,在观察LiveData并获得结果之后,无需在viewModel中将数据更新包装在AsyncTask中.这意味着,你应该总是照顾好

a)查看< - > viewmodel < - >存储库而不是查看< - >存储库和视图< - > viewmodel

b)不要尝试使用不需要的线程.默认情况下,在后台线程(@WorkerThread)上观察LiveData(如果没有使用@MainThread注释),并获取ui-thread(@MainThread)中的值.

  • 无论如何..我认为框架应该提供更易于使用的实用程序,以便在后台安排短期工作.我的意思是..如果您不使用像RxJava这样的外部库,您将被迫使用AsyncTask或IntentService或类似的东西..但为了正确管理它们需要大量的样板代码. (4认同)

svo*_*oid 5

关于问题2:

对于 Kotlin 用户来说,现在有一个非常好的方法来实现这一点,因为从 Room 2.1 开始,就直接支持协程。这里给出了一个简洁的例子。

您可以直接在 DAO 中使用“挂起函数”,它会确保主线程上不执行任何操作:

@Dao
 interface BarDao {

   @Query("SELECT * FROM bar WHERE groupId = 2")
   fun getAllBars(): LiveData<MutableList<Bar>>

   @Query( "SELECT * FROM bar WHERE groupId = 0 LIMIT 1")
   fun getRecentBar(): LiveData<Bar>

   @Insert
   suspend fun insert(bar: Bar)

   @Update
   suspend fun update(bar: Bar)

   @Delete
   suspend fun delete(bar: Bar)

}
Run Code Online (Sandbox Code Playgroud)

然后在你的 viewModel 中你只需:

    fun insert(bar: Bar) = viewModelScope.launch {
        barDao.insert(bar)
    }

    fun update(bar: Bar) = viewModelScope.launch {
        barDao.update(bar)
    }

    fun delete(bar: Bar)= viewModelScope.launch {
        barDao.delete(bar)
    }
Run Code Online (Sandbox Code Playgroud)