如何将 Room 与 LiveData 一起使用?
在之前的文章中,我们讨论了如何在 Android 应用程序中使用 Room 持久性库以及 Room 内部是如何工作的。我们还谈到了我们可以在 Room 的帮助下执行的各种操作。其中之一是将 LiveData 与 Room 一起使用。该房间允许简单集成 LiveData。你只需要从你的 DAO 方法中返回 LiveData,剩下的就交给 Room。
LiveData 可观察查询
运行查询时,您经常希望应用程序的 UI 在数据更改时自动更新。在查询方法描述中使用 LiveData 类型的返回值来完成此操作。
Kotlin
@Dao
interface Course {
@Query("SELECT * FROM courses")
fun getAllLiveData(): LiveData>
}
Kotlin
@Override
public LiveData> getAllLiveData() {
final String _sql = "SELECT * FROM course";
final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
return __db.getInvalidationTracker().createLiveData(new String[]{"course"}, false, new Callable>() {
@Override
public List 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 _result = new ArrayList(_cursor.getCount());
while(_cursor.moveToNext()) {
final GFG _item;
final int _tmpUid;
_tmpUid = _cursor.getInt(_cursorIndexOfUid);
final String _courseName;
_courseName = _cursor.getString(_cursorIndexOfFirstName);
final String _coursePrice;
_coursePrice = _cursor.getString(_cursorIndexOfLastName);
_item = new GFG(_tmpUid,_courseName,_coursePrice);
_result.add(_item);
}
return _result;
} finally {
_cursor.close();
}
}
@Override
protected void finalize() {
_statement.release();
}
});
}
Kotlin
@Dao
interface GFGDao {
@Query("SELECT * from courses where uid = :id LIMIT 1")
fun loadGFGById(id: Int): Flowable
@Insert
fun insertCourses(vararg courses: GFG): Completable
@Delete
fun deleteAllCourses(courses: List): Single
}
Kotlin
@Override
public Completable insertLargeNumberOfGFGs(final GFG... GFGs) {
return Completable.fromCallable(new Callable() {
@Override
public Void call() throws Exception {
__db.beginTransaction();
try {
__insertionAdapterOfGFG.insert(GFGs);
__db.setTransactionSuccessful();
return null;
} finally {
__db.endTransaction();
}
}
});
}
@Override
public Single deleteAllGFGs(final List GFGs) {
return Single.fromCallable(new Callable() {
@Override
public Integer call() throws Exception {
int _total = 0;
__db.beginTransaction();
try {
_total +=__deletionAdapterOfGFG.handleMultiple(GFGs);
__db.setTransactionSuccessful();
return _total;
} finally {
__db.endTransaction();
}
}
});
}
@Override
public Flowable loadGFGById(final int courseID) {
final String _sql = "SELECT * from GFGs where uid = ? LIMIT 1";
final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 1);
int _argIndex = 1;
_statement.bindLong(_argIndex, courseID);
return RxRoom.createFlowable(__db, false, new String[]{"GFGs"}, new Callable() {
@Override
public GFG call() throws Exception {
// Some exception Handling magic
}
@Override
protected void finalize() {
_statement.release();
}
});
}
Kotlin
@Dao
interface GFGDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertGFG(vararg course: GFG) @Update
suspend fun updateGFG(vararg course: GFG) @Delete
suspend fun deleteGFG(vararg course: GFG) @Query("SELECT * FROM course")
suspend fun loadAllGFG(): Array
}
Kotlin
@Override
public Object insertGFG(final Course[] GFG, final Continuation super Unit> p1) {
return CoroutinesRoom.execute(__db, true, new Callable() {
@Override
public Unit call() throws Exception {
__db.beginTransaction();
try {
__insertionAdapterOfCourse.insert(GFG);
__db.setTransactionSuccessful();
return Unit.INSTANCE;
} finally {
__db.endTransaction();
}
}
}, p1);
}
更新数据库时,Room 会生成更新 LiveData 所需的所有代码。生成的代码如下所示:
科特林
@Override
public LiveData> getAllLiveData() {
final String _sql = "SELECT * FROM course";
final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
return __db.getInvalidationTracker().createLiveData(new String[]{"course"}, false, new Callable>() {
@Override
public List 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 _result = new ArrayList(_cursor.getCount());
while(_cursor.moveToNext()) {
final GFG _item;
final int _tmpUid;
_tmpUid = _cursor.getInt(_cursorIndexOfUid);
final String _courseName;
_courseName = _cursor.getString(_cursorIndexOfFirstName);
final String _coursePrice;
_coursePrice = _cursor.getString(_cursorIndexOfLastName);
_item = new GFG(_tmpUid,_courseName,_coursePrice);
_result.add(_item);
}
return _result;
} finally {
_cursor.close();
}
}
@Override
protected void finalize() {
_statement.release();
}
});
}
__db.getInvalidationTracker() 用于前面的代码()。 createLiveData() 接受一个 tableNames 数组、inTransaction 布尔标志和一个可调用的 computeFunction。
GeekTip: RoomTrackingLiveData uses tableNames to monitor for changes.
- inTransaction 参数指定查询是否必须作为事务执行。
- computeFunction 是一个可调用的,只要观察到的表发生变化就会调用它。
我们还可以看到,computeFunction 的 call() 方法执行了实际的查询执行。每当观察者开始观察 LiveData 或观察到的表中发生任何更改时,都会调用它。
RxJava 的房间
在之前的文章中,我们讨论了如何在 Android 应用程序中使用 Room 持久性库。我们还讨论了 Room DAO 可以执行的各种操作。使用 Room,使用 RxJava 可观察对象变得轻而易举。我们需要在构建中包含以下依赖项,以从您的 DAO 方法返回 RxJava 可观察对象。
首先,毕业:
dependencies {
def room_version = "2.2.5"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
// Geeks for Geeks RxJava support for Room
implementation "androidx.room:room-rxjava2:$room_version"
}
RxJava Room 的响应式查询包括以下对 RxJava2 类型返回值的支持:
- @Query 方法: Room 接受 Publisher、Flowable 和 Observable 返回值。
- @Insert、@Update 和 @Delete 方法:Room 2.1.0 和更高版本支持 Completable、
和 类型的返回值。
科特林
@Dao
interface GFGDao {
@Query("SELECT * from courses where uid = :id LIMIT 1")
fun loadGFGById(id: Int): Flowable
@Insert
fun insertCourses(vararg courses: GFG): Completable
@Delete
fun deleteAllCourses(courses: List): Single
}
以下是如何将这些方法付诸实践的示例:
科特林
@Override
public Completable insertLargeNumberOfGFGs(final GFG... GFGs) {
return Completable.fromCallable(new Callable() {
@Override
public Void call() throws Exception {
__db.beginTransaction();
try {
__insertionAdapterOfGFG.insert(GFGs);
__db.setTransactionSuccessful();
return null;
} finally {
__db.endTransaction();
}
}
});
}
@Override
public Single deleteAllGFGs(final List GFGs) {
return Single.fromCallable(new Callable() {
@Override
public Integer call() throws Exception {
int _total = 0;
__db.beginTransaction();
try {
_total +=__deletionAdapterOfGFG.handleMultiple(GFGs);
__db.setTransactionSuccessful();
return _total;
} finally {
__db.endTransaction();
}
}
});
}
@Override
public Flowable loadGFGById(final int courseID) {
final String _sql = "SELECT * from GFGs where uid = ? LIMIT 1";
final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 1);
int _argIndex = 1;
_statement.bindLong(_argIndex, courseID);
return RxRoom.createFlowable(__db, false, new String[]{"GFGs"}, new Callable() {
@Override
public GFG call() throws Exception {
// Some exception Handling magic
}
@Override
protected void finalize() {
_statement.release();
}
});
}
我们可以从自动生成的代码中看到 Room 使用 fromCallable()运算符创建了 Completable 和 Single 。在 RxRoom。 createFlowable, Room 使用 Flowable 要创建 Flowable,请使用 create()。 callable 的 call() 方法中的代码类似于非响应式实现。
房间中的 Kotlin 协程
在之前的文章中,我们讨论了 Room 持久性库以及使用它的好处。使用 Room 的好处之一是它可以很容易地与其他库集成,例如 Kotlin Coroutines。那么让我们来谈谈如何在 Room 的帮助下做到这一点。首先,我们必须为 Kotlin 协程支持添加以下依赖项:
dependencies {
def room_version = "2.2.5"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
// Basic extension for Kotlin to make Room work
implementation "androidx.room:room-ktx:$room_version"
}
Kotlin 协程可用于编写异步方法
您可以使用暂停 Kotlin 关键字来使用 Kotlin 协程使您的 DAO 方法异步。这可以防止它们在主线程上执行。
科特林
@Dao
interface GFGDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertGFG(vararg course: GFG) @Update
suspend fun updateGFG(vararg course: GFG) @Delete
suspend fun deleteGFG(vararg course: GFG) @Query("SELECT * FROM course")
suspend fun loadAllGFG(): Array
}
上面列出的所有方法都是由 Room 实现的。挂起函数的实现与非挂起函数的实现非常相似。
科特林
@Override
public Object insertGFG(final Course[] GFG, final Continuation super Unit> p1) {
return CoroutinesRoom.execute(__db, true, new Callable() {
@Override
public Unit call() throws Exception {
__db.beginTransaction();
try {
__insertionAdapterOfCourse.insert(GFG);
__db.setTransactionSuccessful();
return Unit.INSTANCE;
} finally {
__db.endTransaction();
}
}
}, p1);
}
结论
两种实现的唯一区别在于,在挂起函数的情况下,CoroutinesRoom.execute 负责停止执行流程。这就是将 Room 与 LiveData、RxJava 和 Kotlin 协程一起使用。我们希望您发现这篇 Geeks for Geeks 文章很有趣。