RoomDatabase(Android 数据库 Room) + LiveData 完成多状态任务管理机制

926 阅读2分钟

问题场景:例如在小红书上发布一篇图文笔记,从编辑完图片到发布成功,中间需要经过若干步骤,如何对这些中间任务进行管理?

从上图可以看出整个任务的有一下特点:

  1. 任务有多个状态。
  2. 各状态顺序执行。
  3. 任务可以在任意状态时,被打断。
  4. 任务可以从被打断的状态重入。

任务从被打断的状态重入,是整个问题的关键点,要想重入就必须保存状态信息,Android提供的数据库恰好可以解决这个问题。

使用数据库(RoomDatabase)来管理任务状态

将任务状态作为一条信息存入数据库,每次状态改变就改变这条信息。重入时,只需要直接读取数据库,就可以进行接下来的任务了。

RoomDatabase 是什么

RoomDatabase是Android Architecture Components(Android架构组件)的一部分。它是SQLite的一个抽象层,SQLite是许多Android应用程序中使用的流行的数据库管理系统。RoomDatabase提供了一个易于使用、面向对象的接口,用于在Android应用程序中使用SQLite数据库。 具体使用方法可以参考developer.android.com/training/da… 简单理解就是我们可以利用RoomDatabase来直接访问数据库,奇妙的是,RoomDatabase 返回的查询结果可以是一个LiveData ,当数据库结构更新时,可以直接响应这个liveData的observe。

下面写一下伪代码:

@Entity
data class Article(
    @PrimaryKey val id: Int,
    val imgPath: String,
    val text: String,
    val status: Int // 用来表示上传任务的状态
)

Article 类表示上传任务信息的实体类,其中status表示任务进行到了什么状态。

@Dao
interface ArticleDao {
    @Insert
    suspend fun insert(info: Article): Long

    @Update
    suspend fun update(info: Article)

    @Delete
    suspend fun delete(info: Article)

    @Query("SELECT * FROM info ORDER BY id DESC")
    fun getArticle(id: Long): LiveData<Article>

ArticleDao 是用来跟数据库进行交互的接口。

@Database(entities = [Article::class], version = 1)
abstract class ArticleDatabase : RoomDatabase() {
    abstract fun articleDao(): ArticleDao

    companion object {
        @Volatile
        private var instance: ArticleDatabase? = null

        fun getInstance(context: Context): ArticleDatabase {
            return instance ?: synchronized(this) {
                instance ?: Room.databaseBuilder(
                    context.applicationContext,
                    ArticleDatabase::class.java,
                    "ArticleDatabase_database"
                ).fallbackToDestructiveMigration().build().also { instance = it }
            }
        }
    }
}

ArticleDatabase 是用来生成 RoomDatabase 实例,通过 ArticleDao 定义的接口来访问数据库。

val articleDatabase = ArticleDatabase().getInstance(context).getArticle(id)
articleData.observe { article ->
    when (article.status) {
        1 -> {
            val newArticle = processThisStatus(article) // 处理这个状态数据
            articleDatabase.update(newArticle) // 更新至下一个状态
        }
        2 -> {/*同上*/}
        3 -> {/*同上*/}
    }
}

通过ArticleDatabase 拿到 LiveData,就可以在Observe中处理任务。任务的状态改变,又会响应Observe,直到任务完成后,将任务从数据库中删除。