前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android Architecture Components Part1:Room

Android Architecture Components Part1:Room

作者头像
Rouse
发布2019-07-16 18:06:23
7790
发布2019-07-16 18:06:23
举报
文章被收录于专栏:Android补给站Android补给站

Android Architecture Components(AAC)首次发布与2017 GoogleI/O大会,经过近一年的维护,现在Google团队已经发布了稳定版(v1.1.1)。能够更好的帮助我们来构建自己的App应用,如果你还没有了解ACC现在时间刚刚好,来不及解释,赶紧上车吧。

AAC是一个架构组件,它能帮忙我们更好的来管理我们的App,方便我们的开发。它能帮助我们的App更好的存储数据、管理生命周期、进行模块化、避免常见的错误、减少样板文件的编写。

AAC主要由4个单一组件组成,分别为:Room、LiveData、Lifecycle与ViewModel。它们每一个都是独立存在的组件,我们可以单独使用其中几个,又或者可以将它们全部整合到一起。所以对于AAC它提供了更好的使用灵活性,方便我们集成到我们的App中。

今天主要是对AAC其中的Room组件进行分析。Room是一个稳健的SQL对象映射库,用来帮助我们快速的实现数据本地存储。至于为何要使用本地数据库,自然是当用户无网络或者网络差的时候,能够更好的提高用户对我们App的体验。

添加依赖

在使用Room之前,我们还是要在项目中对其进行依赖添加。 首先在你的项目的根目录下的build.gradle中添加google()库,代码如下:

代码语言:javascript
复制
1allprojects {
2    repositories {
3        jcenter()
4        google()
5    }
6}

之后打开你的App或者module中的build.gradle文件,在dependencies中添加如下代码:

代码语言:javascript
复制
1dependencies {
 2    def room_version = "1.1.0" // or, for latest rc, use "1.1.1-rc1"
 3    implementation "android.arch.persistence.room:runtime:$room_version"
 4    annotationProcessor "android.arch.persistence.room:compiler:$room_version"
 5    // optional - RxJava support for Room
 6    implementation "android.arch.persistence.room:rxjava2:$room_version"
 7    // optional - Guava support for Room, including Optional and ListenableFuture
 8    implementation "android.arch.persistence.room:guava:$room_version"
 9    // Test helpers
10    testImplementation "android.arch.persistence.room:testing:$room_version"
11}

Room

上面的依赖添加完成后,接下来我们可以正式使用Room。在Android App中进行本地数据的存储都是使用SQLite,当我们使用原生的SQLite进行本地数据库的编写时,我们不仅要定义数据库结构,还要创建SQLiteHelper,编写一连串的SQL语句。这样代码量与复杂度不断上升,这不是我们想要的。而Room正好可以帮助我们减少代码、简化复杂度。

对于Room的使用主要由三部分构成:

  1. Entity:标识数据库中的表结构
  2. DAO: 标识提供获取数据库表中的数据方法
  3. Database:标识所需要创建的数据库

以上三部分在代码中都是通过注释来实现,从而达到代码的精简。

Entity

Entity作用在model上,即我们与数据表中的字段所匹配的model类。现在我们来建立一个联系人相关的model,对于正常的model建立如下:

代码语言:javascript
复制
1data class ContactsModel(val id: Int, val name: String, val phone: String)

现在我们要把ContactsModel映射到数据库中的一种表,只需进行如下操作:

代码语言:javascript
复制
 1@Entity(tableName = "contacts")
 2data class ContactsModel(
 3        @PrimaryKey
 4        @ColumnInfo(name = "contacts_id")
 5        val id: Int,
 6        @ColumnInfo(name = "name")
 7        val name: String,
 8        @ColumnInfo(name = "phone")
 9        val phone: String
10)

首先我们在ContactsModel中添加@Entity注释,表明它将映射成一种表。在Entity中可以通过使用tableName来为该表命名,这里将其命名未contacts。

除此之外,使用@ColumnInfo来标明表中的字段,@PrimaryKey来标明表的主键。其中@ColumnInfo也可以通过(name = "name")来命名字段名。当然还有别的注释例如外键的标明:@ForeignKey

DAO

数据库表建好了,现在是提供操作数据表中的数据的方法。

代码语言:javascript
复制
1@Dao
 2interface ContactsDao {
 3    @Query("SELECT * FROM contacts")
 4    fun getAllContacts(): List<ContactsModel>
 5    @Query("SELECT * FROM contacts WHERE contacts_id = :id")
 6    fun getContactsById(id: Int): LiveData<ContactsModel>
 7    @Insert(onConflict = OnConflictStrategy.REPLACE)
 8    fun insertContacts(contactsModel: ContactsModel)
 9    @Query("UPDATE contacts SET name = :name AND phone = :phone WHERE contacts_id = :id")
10    fun updateContacts(id: Int, name: String, phone: String)
11    @Query("DELETE FROM contacts WHERE contacts_id = :id")
12    fun deleteContacts(id: Int)

这里我们只需创建一个接口,通过@Dao来标明它是提供操作数据表的方法集。要注意它必须为interface,在接口中我们只需定义接口方法即可。与平常的接口方法定义不同的是,我们必须在每一个接口方法上通过注释来标明该方法的作用。

例如getAllContacts()方法,我们为了让它实现获取contacts表中的所有数据,我们需要在其方法中添加@Query注释,由于是查询方法,自然是使用Query,如果是插入方法就是Insert(第三个方法)。其次()中的内容就是正常的查询语句。这里是获取所有的Contacts,所以我们使用

代码语言:javascript
复制
1@Query("SELECT * FROM contacts")

对于有参数的sql语句编写,可以查看第二个方法,参数值只需在对应的方法参数名前加入:前缀,这就是传参的格式。

代码语言:javascript
复制
1@Query("SELECT * FROM contacts WHERE contacts_id = :id")
2fun getContactsById(id: Int): LiveData<ContactsModel>

Room就是这么简单,通过定义接口与接口方法的形式,再结合注释来简化代码量与复杂度。当然最终Room会根据注释,编译器会帮我们实现这些接口方法。我们可以build项目,然后我们就可以搜索到ContactsDao_Impl类,这个读者可以自行尝试。本质是ContactsDao_Impl实现了ContactsDao接口。

Room的强大之一是:它可以在编译时检测你的SQL语句是否编写正确,如果编写错误将导致编译失败。这样就可以避免App在运行时导致崩溃。这个读者可以自行测试一下。

Database

现在数据表有了,对表的操作方法也有了,最后就差数据库来保存各个数据表了。Talk is cheap. Show me the code。

代码语言:javascript
复制
 1@Database(entities = arrayOf(ContactsModel::class), version = 1)
 2abstract class ContactsDataBase : RoomDatabase() {
 3    abstract fun contactsDao(): ContactsDao
 4    companion object {
 5        private var instance: ContactsDataBase? = null
 6        fun getInstance(context: Context): ContactsDataBase {
 7            if (instance == null) {
 8                instance = Room.databaseBuilder(context.applicationContext,
 9                        ContactsDataBase::class.java,
10                        "contacts.db").build()
11            }
12            return instance as ContactsDataBase
13        }
14    }
15}

没错,还是使用注释,这里我们定义ContactsDataBase抽象类,让它继承RoomDatabase抽象类。当然也是同@Database来标明它是一个数据库。它接收两个参数,分别为entities与version,前者接收的类型是Class[]数组,内容为对于表的Class;后者是int的数据库版本号。

在ContactsDataBase中还需定义一个抽象方法,让它返回由@Dao注释的ContactsDao,即提供获取数据表的方法。本质的为数据库暴露操作数据表的入口。至于它的具体方法实现也可以通过build来查看对应的自动生成文件ContactsDataBase_Impl类。

因为contactsDao是数据库的唯一入口,避免每次对数据库进行操作时都创建ContactsDataBase实例,如上代码我们可以使用单例模式来减少实例频繁创建的开销。

使用

经过上面的Entity、DAO与Database的创建,现在我们已经有了完整的本地数据库结构。接下来我们来看史上最简数据库使用的调用代码:

代码语言:javascript
复制
1private val mContactsDao by lazy { ContactsDataBase.getInstance(application).contactsDao() }
2fun getContactsById(id: Int): LiveData<ContactsModel> = mContactsDao.getContactsById(id)

你没看错只需两行代码,我们就能获取数据库中Contacts表中的所用数据。

第一行代码我们获取了ContactsDao实例,该实例包含操作数据表的所以方法。而第二行代码就是调用ContactsDao中的操作方法。返回我们所需的数据。

在第二行代码,细心的你们可能会发现它返回了LiveData类型数据。它是ACC的另一强大组件,这也是Room的另一强大之处,它可以直接返回LiveData数据类型,完美与LiveData结合。至于LiveData的作用,敬请关注下一篇文章:

Android Architecture Components Part2:LiveData

总结

如果你的App使用了Room,那么你的App本地数据获取架构将会是这样的

最后文章中的代码都可以在Github中获取到。使用时请将分支切换到: 

feat_architecture_component

项目地址:

https://github.com/idisfkj/android-api-analysis

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-06-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android补给站 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 添加依赖
  • Room
    • Entity
      • DAO
        • Database
          • 使用
          • 总结
          相关产品与服务
          数据库
          云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档