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

问题描述 投票:14回答:4

我有一个Simple DAO包括CRUD功能

feed entry DAO.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);

}

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

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

viewModel.getFeedEntrys().observe(this,entries -> {...});

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

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

我有2个问题:

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

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

android android-room android-architecture-components android-livedata
4个回答
5
投票
  1. 我可以使用LiveData来包装删除,插入,更新呼叫吗?

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

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

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

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

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

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


1
投票

您也可以在抽象类中使用@Dao注释,因此:

  1. 创建一个抽象的@Dao BaseDao类,使用抽象方法@Insert insert(entities)和具体的方法insert(entities, callback)做那个丑陋的AsyncTask工作,在@Insert insert(entities)上调用抽象onBackground,在onPostExecute上调用你的回调。
  2. 让你的FeedEntryDAO也抽象扩展BaseDao@Query方法摘要。

Kotlin的结果使用非常漂亮:

database.entityDao().insert(entities) { ids ->
    // success
}

1
投票

对于第二个问题,还有另一种更适合AsyncTask的替代品;这是使用java Executor,好消息是你可以使用Executor的单个实例代替所有CRUD操作的AsyncTask的多个实例。

演示示例

public class Repository {

    private static Repository instance;
    private MyDatabase mDatabase;
    private Executor mExecutor = Executors.newSingleThreadExecutor();

    private Repository(Application application) {
        mDatabase = MyDatabase.getInstance(application.getApplicationContext());
    }

    public static Repository getInstance(Application application) {
        if (instance == null) {
            instance = new Repository(application);
        }
        return instance;
    }


    public void insert(final MyModel model) {

        mExecutor.execute(new Runnable() {
            @Override
            public void run() {
                mDatabase.getMyModelDAO().insert(model);
            }
        });
    }

    public void update(final MyModel model) {
        mExecutor.execute(new Runnable() {
            @Override
            public void run() {
                mDatabase.getMyModelDAO().update(model);
            }
        });
    }

    public void delete(final MyModel model) {
        mExecutor.execute(new Runnable() {
            @Override
            public void run() {
                mDatabase.getMyModelDAO().delete(model);
            }
        });
    }

}

0
投票

要使应用程序的UI在数据更改时自动更新,请在查询方法描述中使用LiveData类型的返回值。 Room会生成所有必要的代码,以便在更新数据库时更新LiveData。

@Dao
interface MyDao {
    @Query("SELECT first_name, last_name FROM user WHERE region IN (:regions)")
    fun loadUsersFromRegionsSync(regions: List<String>): LiveData<List<User>>
}

注意:从1.0版开始,Room使用查询中访问的表列表来决定是否更新LiveData的实例。

© www.soinside.com 2019 - 2024. All rights reserved.