今天学习Repository和WorkManager

Repository

Repository pattern也是一种设计模式,叫做存储库模式。看一下官方的原文:

A repository mediates between data sources (such as persistent models, web services, and caches) and the rest of the app.

大意就是一个Repository相当于在数据源(持久化实体类,网络服务,缓存)和app其余的服务之间的中间层。简而言之,就是提供一个数据操作代理层。调用者不需要知道数据是从哪来,如何处理,只需要使用数据即可。这样有几个好处:

  1. 代码更容易维护,切换数据源的时候业务代码不需要更改

  2. 数据处理逻辑和业务逻辑分离,可以对这两个代码分别进行测试

  3. 减少代码重复

  4. 降低代码出错的几率

为什么要有Repository

经过前几天的学习,我们已经学习了ROOM以及DAO层数据的访问,那么还需要Repository干什么呢?通过上面的优点我们可以知道,避免直接访问数据。同事也解决了多数据源的问题,一个App的数据源可以是多个,数据库,接口等等。Repository对这两种情况进行封装,可以以一种统一的方式进行数据的拉取。

所以Repository其实是一种代码规范,并不是组件。

Repository例子

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@Singleton
class PlantRepository @Inject constructor(private val plantDao: PlantDao) {
    
    // use the dao
    fun getPlants() = plantDao.getPlants()

    fun getPlant(plantId: String) = plantDao.getPlant(plantId)

    fun getPlantsWithGrowZoneNumber(growZoneNumber: Int) =
        plantDao.getPlantsWithGrowZoneNumber(growZoneNumber)

    // use the network service
    fun requestApi(): Plant
}

项目中的实际运用

在市局测温项目中,实际上对Repository的使用更为复杂,整体的结构为首先定义一层datasource的接口类,然后在定义datasource的实现类,这里仅仅定义了一个remotedatasource的实现类,根据命名我感觉原本的架构想法应该是对于数据调接口一个实现类,数据库操作一个实现类。

但是实际的写法是调接口获取数据和从数据库中获取数据都在remotedatasource实现类中实现了。

最后定义了Repository类去实现datasource的接口类,在Repository实现类中调用了remotedatasource实现类。

整体一共需要三个类才能完成Repository中间层的设计。

市局测温项目整体上都采用了Repository的设计模式,但是在代码的清晰度方面有所下降,刚看代码的时候如果不了解Repository,那么对于一个获取数据为什么要设计的如此复杂就会充满疑惑。

官方给的样例中只需要一个Repository就完成了中间层的设计,对于未来代码的编写,我认为可以跟着官方的思路走,让代码更清洗一点,Repository就作为一个实现类,引入Dao层或者Web Service层去实现数据的获取。

WorkManager

WorkManager说白了就是来管理后台任务的。

WorkManager比较优秀的点在于能保证任务一定会被执行,及时app不运行,哪怕设备重启,也能在适当的时候被执行。WorkManager有自己的数据库,所以能一定被执行。

上面这个特性也广泛运用于其它程序中,比如datai推数据,如果要保证数据的正常推送,避免因为宕机等因素造成的数据推送紊乱。除了简单的使用标志位外,还可以使用一张表来记录数据的推送,这样及时数据推送失败,那么下一次依然能够完整的推送数据。

WorkManager的使用

集成Worker()类来完成work的定义,doWork()执行任务。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
class UploadWorker(appContext: Context, workerParams: WorkerParameters):
       Worker(appContext, workerParams) {
   override fun doWork(): Result {

       // Do the work here--in this case, upload the images.
       uploadImages()

       // Indicate whether the work finished successfully with the Result
       return Result.success()
   }
}

定义完work后,还需要来调度work,创建WorkRequest来调度任务。下面就是一个一次性任务的调度。

1
2
3
val uploadWorkRequest: WorkRequest =
   OneTimeWorkRequestBuilder<UploadWorker>()
       .build()

最后需要将WorkRequest提交到WorkManager

1
2
3
WorkManager
    .getInstance(myContext)
    .enqueue(uploadWorkRequest)

这只是一个简单的WorkManager的使用。

更多的使用方法直接看官方文档的使用指南。

https://developer.android.google.cn/topic/libraries/architecture/workmanager?hl=zh-cn