当前位置:   article > 正文

将 Room 与 LiveData 和其他第三方库一起使用_room livedata

room livedata

LiveData 的房间

Room 非常容易支持 LiveData 的集成。您只需要从您的 DAO 方法中返回 LiveData,Room 会为您处理其他所有事情。

使用 LiveData 的可观察查询

执行查询时,您通常希望应用程序的 UI 在数据更改时自动更新。为此,LiveData请在查询方法描述中使用类型的返回值。

@Dao
interface UserDao {
    @Query("SELECT * FROM users")
    fun getAllLiveData(): LiveData<List<User>>
}
  • 1
  • 2
  • 3
  • 4
  • 5

LiveDataRoom 会在数据库更新时生成所有必要的代码来更新。生成的代码如下所示:

@Override
public LiveData<List<User>> getAllLiveData() {
  final String _sql = "SELECT * FROM users";
  final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
  return __db.getInvalidationTracker().createLiveData(new String[]{"users"}, false, new Callable<List<User>>() {
    @Override
    public List<User> call() throws Exception {
      final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
      try {
        final int _cursorIndexOfUid = CursorUtil.getColumnIndexOrThrow(_cursor, "uid");
        final int _cursorIndexOfFirstName = CursorUtil.getColumnIndexOrThrow(_cursor, "first_name");
        final int _cursorIndexOfLastName = CursorUtil.getColumnIndexOrThrow(_cursor, "last_name");
        final List<User> _result = new ArrayList<User>(_cursor.getCount());
        while(_cursor.moveToNext()) {
          final User _item;
          final int _tmpUid;
          _tmpUid = _cursor.getInt(_cursorIndexOfUid);
          final String _tmpFirstName;
          _tmpFirstName = _cursor.getString(_cursorIndexOfFirstName);
          final String _tmpLastName;
          _tmpLastName = _cursor.getString(_cursorIndexOfLastName);
          _item = new User(_tmpUid,_tmpFirstName,_tmpLastName);
          _result.add(_item);
        }
        return _result;
      } finally {
        _cursor.close();
      }
    }

    @Override
    protected void finalize() {
      _statement.release();
    }
  });
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

在上面的代码中,__db.getInvalidationTracker().createLiveData()需要tableNames array、inTransaction布尔标志和computeFunction可调用。

  • tableNames用于RoomTrackingLiveData观察变化。
  • inTransaction指示查询是否必须作为事务执行。
  • computeFunction是一个可调用对象,只要观察到的表有任何更改,就会调用它。

我们还可以看到 的call()方法computeFunction实际执行了我们的查询。当观察者开始观察 LiveData 或观察到的表中发生任何更改时,都会调用它。

使用 RxJava 的房间

为了从你的 DAO 方法返回 RxJava observables,我们需要在我们的build.gradle第一个中添加以下依赖项:

dependencies {
  def room_version = "2.2.5"

  implementation "androidx.room:room-runtime:$room_version"
  kapt "androidx.room:room-compiler:$room_version"

  // RxJava support for Room
  implementation "androidx.room:room-rxjava2:$room_version"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

使用 RxJava 的响应式查询

Room 为 RxJava2 类型的返回值提供以下支持:

  • @QueryPublisher方法:Room 支持类型为 、Flowable和的返回值Observable。
  • @Insert, @Update, 和@Delete方法:Room 2.1.0 和更高版本支持返回值类型Completable,Single和Maybe.
@Dao
interface UserDao {
    @Query("SELECT * from users where uid = :id LIMIT 1")
    fun loadUserById(id: Int): Flowable<User>

    @Insert
    fun insertUsers(vararg users: User): Completable

    @Delete
    fun deleteAllUsers(users: List<User>): Single<Int>
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

这些方法的实现如下所示:

@Override
public Completable insertLargeNumberOfUsers(final User... users) {
  return Completable.fromCallable(new Callable<Void>() {
    @Override
    public Void call() throws Exception {
      __db.beginTransaction();
      try {
        __insertionAdapterOfUser.insert(users);
        __db.setTransactionSuccessful();
        return null;
      } finally {
        __db.endTransaction();
      }
    }
  });
}@Override
public Single<Integer> deleteAllUsers(final List<User> users) {
  return Single.fromCallable(new Callable<Integer>() {
    @Override
    public Integer call() throws Exception {
      int _total = 0;
      __db.beginTransaction();
      try {
        _total +=__deletionAdapterOfUser.handleMultiple(users);
        __db.setTransactionSuccessful();
        return _total;
      } finally {
        __db.endTransaction();
      }
    }
  });
}@Override
public Flowable<User> loadUserById(final int id) {
  final String _sql = "SELECT * from users where uid = ? LIMIT 1";
  final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 1);
  int _argIndex = 1;
  _statement.bindLong(_argIndex, id);
  return RxRoom.createFlowable(__db, false, new String[]{"users"}, new Callable<User>() {
    @Override
    public User call() throws Exception {
      //Implementation 
    }

    @Override
    protected void finalize() {
      _statement.release();
    }
  });
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

从自动生成的代码中,我们可以看到 Room 正在使用fromCallable()操作符来创建Completable和Single。中,Room 用于创建。RxRoom.createFlowableFlowable.create()Flowable

可调用方法内部的代码call()类似于非反应式实现。

带有 Kotlin 协程的房间

首先,我们需要为 Kotlin 协程支持添加以下依赖项:

dependencies {
  def room_version = "2.2.5"

  implementation "androidx.room:room-runtime:$room_version"
  kapt "androidx.room:room-compiler:$room_version"  // Kotlin Extensions and Coroutines support for Room
  implementation "androidx.room:room-ktx:$room_version"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

使用 Kotlin 协程编写异步方法

您可以将suspendKotlin 关键字添加到您的 DAO 方法中,以使用 Kotlin 协程功能使它们异步。这确保它们不能在主线程上执行。

@Dao
interface UserDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertUsers(vararg users: User)    @Update
    suspend fun updateUsers(vararg users: User)    @Delete
    suspend fun deleteUsers(vararg users: User)    @Query("SELECT * FROM users")
    suspend fun loadAllUsers(): Array<User>
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

Room 生成上述所有方法的实现。功能的实现suspend与非挂起的非常相似。

@Override
public Object insertUsers(final User[] users, final Continuation<? super Unit> p1) {
  return CoroutinesRoom.execute(__db, true, new Callable<Unit>() {
    @Override
    public Unit call() throws Exception {
      __db.beginTransaction();
      try {
        __insertionAdapterOfUser.insert(users);
        __db.setTransactionSuccessful();
        return Unit.INSTANCE;
      } finally {
        __db.endTransaction();
      }
    }
  }, p1);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

在这里,异步执行传递的可调用对象。执行不可用。CoroutinesRoom.executeCoroutinesRoom.execute

非挂起函数如下所示:

@Override
public void insertUsers(final User... users) {
  __db.assertNotSuspendingTransaction();
  __db.beginTransaction();
  try {
    __insertionAdapterOfUser.insert(users);
    __db.setTransactionSuccessful();
  } finally {
    __db.endTransaction();
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

两种实现之间的唯一区别是,在suspend函数的情况下,CoroutinesRoom.execute负责暂停执行流。

这完全是关于在 Room 中使用 LiveData、RxJava 和 Kotlin 协程。

如果大伙有什么好的学习方法或建议欢迎大家在评论中积极留言哈,希望大家能够共同学习、共同努力、共同进步。

小编在这里祝小伙伴们在未来的日子里都可以 升职加薪,当上总经理,出任CEO,迎娶白富美,走上人生巅峰!!

不论遇到什么困难,都不应该成为我们放弃的理由!

很多人在刚接触这个行业的时候或者是在遇到瓶颈期的时候,总会遇到一些问题,比如学了一段时间感觉没有方向感,不知道该从那里入手去学习,需要一份小编整理出来的学习资料的关注我主页或者点击微信卡片即可免费领取~

这里是关于我自己的Android 学习,面试文档,视频收集大整理,有兴趣的伙伴们可以看看~

如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言,一定会认真查询,修正不足,谢谢。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/477731
推荐阅读
相关标签
  

闽ICP备14008679号