文章目录

  • Compose如虎添翼 -- 搭配Flow、Room!!!
    • 一、需求一览
    • 二、Compose UI开发
    • 三、Room集成及使用
      • 3.1、在使用kotlin编写的gradle脚本中集成
      • 3.2、使用方式
        • 3.2.1、数据库表(Table)
        • 3.2.2、数据访问对象(DAO-DataAccessObjects )
        • 3.2.3、数据库(Database)
        • 3.2.4、添加节气数据到数据库
    • 四、Compose + Flow
    • 五、小结

Compose如虎添翼 – 搭配Flow、Room!!!

Compose系列文章,请点原文阅读。原文:是时候学习Compose了!

通过上文Compose结合ViewModel、LiveData的示例,这次我们可以继续前进一步了。其实Room、Flow和Compose并没有直接关系,只是Flow可以转换为LiveData或者State,而LiveData和Compose的搭配我们前文已经说了。Jetpack Room又支持返回Flow类型的数据,单介绍Flow也没多少意思,所以索性加上Jetpack Room简单开发示例来丰富篇幅。

一、需求一览

这节的主题是搭配Kotlin Flow以及Jetpack Room来示例一款24节气应用,要求列表形式展示相关节气信息,图片来源于网络。同时更改Room数据库信息后需要及时将修改过的信息刷新并显示在页面上,大致的UI效果如下所示吧(自作多情的加了一个小的动画):

特别鸣谢:这节内容,用到了一些24节气的图片素材,感谢UI小姐姐:@雪莉莉 【Dribbble】【站酷】。

二、Compose UI开发

首先这节内容我们需要展示网络图片,Compose加载网络图片需要一个工具库 Image Loadding。请参考官方主页:https://google.github.io/accompanist/,这些工具库提供了有图片加载、类似ViewPager、下拉刷新等的功能,大家可以择需获取。我们只需要一个图片加载库,官方给了Glide和Coil的示例,我们使用后者做演示。

在build.gradle中添加依赖,accompanist-coil的版本请和Compose的版本对应,否则编译会出现错误。目前示例:Compose是1.0.0-beta07版本,accompanist-coil是0.10.0版本:

repositories {mavenCentral()
}dependencies {implementation "com.google.accompanist:accompanist-coil:<version>"
}

然后使用方式很简单,使用 painter: Painter 参数,代码如下(Preview模式下无法预览到网络图片):

Image(painter = rememberCoilPainter(request = "https://picsum.photos/300/300",),contentDescription = "Desc",
)

既然要写列表,那么肯定是先写ItemView,图片的问题已经搞定了,还剩一个动画效果:点击ItemView,节气介绍内容向下弹出。其实也很简单,用到了官方还在实验阶段的一个API - AnimatedVisibility,该可组合函数需要一个boolean类型的参数,就可以实现默认的弹出收回的效果,直接看代码:

@ExperimentalAnimationApi
@Composable
fun SolarTermsItem(entity: SolarTerm) {val isShowDetail = remember {mutableStateOf(false)}Column(modifier = Modifier.fillMaxWidth().padding(8.dp)) {Row(modifier = Modifier.fillMaxWidth().clickable(onClick = {isShowDetail.value = !isShowDetail.value})) {//图片Image(painter = rememberCoilPainter(request = entity.imgUrl,),contentDescription = "image of term",modifier = Modifier.fillMaxWidth(0.5f).wrapContentHeight().clip(RoundedCornerShape(10)))//右侧节气信息Column(modifier = Modifier.fillMaxWidth().padding(start = 8.dp)) {Text(text = entity.name,fontSize = 24.sp,fontWeight = FontWeight.ExtraBold)Spacer(modifier = Modifier.height(8.dp))Text(text = entity.time,fontSize = 16.sp,fontWeight = FontWeight.Bold)Spacer(modifier = Modifier.height(8.dp))Text(text = entity.mark,fontSize = 14.sp,fontWeight = FontWeight.Normal)}}//点击item,向下弹出节气的内容介绍,再次点击收回AnimatedVisibility(visible = isShowDetail.value) {Text(text = entity.content,fontSize = 14.sp,fontWeight = FontWeight.Normal,modifier = Modifier.padding(top = 8.dp))}}
}

OK,ItemView写好了,我们先造两条伪数据,如下,然后使用LazyColumn就可以打造出一个竖向的列表了,不需要Adapter不需要LayoutManager,对比之前的开发方式简直能给我乐哭了:

val entityYuShui = SolarTerm(name = "雨水",content = "正月中,天一生水,春始属木,然生木者必水也,故立春后继之雨水。且东风既解冻,则散而为雨矣。",time = "2.18-2.19",mark = "春雨贵如油",imgUrl = "https://cdn.dribbble.com/users/2676519/screenshots/7056971/media/efde75ba876f38cb95ce5b936f481784.jpg?compress=1&resize=1000x750"
)val entityChunFen = SolarTerm(name = "春分",content = "春分者,阴阳相半也。故昼夜均而寒暑平。斗指壬为春分,约行周天,南北两半球昼夜均分,又当春之半,故名为春分。",time = "3.20-3.21",mark = "春分有雨到清明,清明下雨无路行",imgUrl = "https://cdn.dribbble.com/users/2676519/screenshots/7056971/media/cdcf98372abf88a554a53362c6037f2a.jpg?compress=1&resize=1000x750"
)val list = arrayListOf(entityYuShui, entityChunFen)LazyColumn {items(list) {SolarTermsItem(entity = it)}
}

UI写完后,运行起来你应该就可以看到上图的效果了。【哦对了,忘了提醒你一句,网络权限!!!】

三、Room集成及使用

3.1、在使用kotlin编写的gradle脚本中集成

这里我使用的是kotlin来编写Gradle构建脚本的,基于groovy的请直接参考【官网示例】,build.gradle.kts脚本文件添加依赖如下,注意添加kotlin-kapt插件依赖,此处room版本为2.3.0:

plugins {...id("kotlin-kapt")
}dependencies {...//room相关依赖内容implementation ("androidx.room:room-runtime:${rootProject.extra["room_version"]}")// To use Kotlin annotation processing tool (kapt)kapt ("androidx.room:room-compiler:${rootProject.extra["room_version"]}")// optional - Kotlin Extensions and Coroutines support for Roomimplementation ("androidx.room:room-ktx:${rootProject.extra["room_version"]}")// optional - Test helperstestImplementation ("androidx.room:room-testing:${rootProject.extra["room_version"]}")
}

别以为这就配置完了,还有很重要的一个步骤 – 配置注解处理器选项:

android {defaultConfig {//...javaCompileOptions {annotationProcessorOptions {arguments["room.schemaLocation"] = "$projectDir/schemas"arguments["room.incremental"] = "true"arguments["room.expandProjection"] = "true"}}}
  • room.schemaLocation:配置并启用将数据库架构导出到给定目录中的 JSON 文件的功能。
  • room.incremental:启用 Gradle 增量注解处理器。
  • room.expandProjection:配置 Room 以重写查询,使其顶部星形投影在展开后仅包含 DAO 方法返回类型中定义的列。

如果上述步骤丢失的话,编译的时候会报如下错误:
Schema export directory is not provided to the annotation processor so we cannot export the schema. You can either provide room.schemaLocation annotation processor argument OR set exportSchema to false.

3.2、使用方式

3.2.1、数据库表(Table)

数据库中的表,在这里我们可以将上述的 数据类SolarTerm 用相关注解来表示:

原数据类:

data class SolarTerm(val name: String = "",          //节气名:春分val content: String = "",       //简介val time: String = "",          //节气时间:3.20-3.21val mark: String = "",          //相关俗语:春分有雨到清明,清明下雨无路行val imgUrl: String = ""         //图片地址
)

添加相关注解:

@Entity(tableName = "term")
data class SolarTerm(@PrimaryKey(autoGenerate = true)@ColumnInfo(name = "id", typeAffinity = ColumnInfo.INTEGER)val id: Int? = null,            //主键@ColumnInfo(name = "name", typeAffinity = ColumnInfo.TEXT)val name: String = "",          //节气名:春分val content: String = "",       //简介val time: String = "",          //节气时间:3.20-3.21val mark: String = "",          //相关俗语:春分有雨到清明,清明下雨无路行val imgUrl: String = ""         //图片地址
)
  • @Entity 表示这个数据类对应数据库中的表,表名(tableName)为 “term”
  • @PrimaryKey 表示id字段为主键,自增
  • @ColumnInfo表示列相关信息,name是列名,typeAffinity是字段类型,文本、数字等

3.2.2、数据访问对象(DAO-DataAccessObjects )

数据库表有了,我们需要使用数据访问对象(DAO)来访问该表中的内容,Room也提供了@Dao的注解:

@Dao
interface SolarTermDao {/*** 查询所有的节气数据*/@Query("SELECT * FROM term")fun queryAll(): Flow<List<SolarTerm>>/*** 插入一条数据*/@Insert()fun insert(entity: SolarTerm)/*** 清空term表中所有内容*/@Query("DELETE FROM term")fun delete()
}
  • Query 表示查询,SELECT * FROM term 表示我们需要从term表中查出所有的数据;
  • Insert表示插入数据;

注意 :在queryAll()方法,我们返回的是Flow类型的数据;

3.2.3、数据库(Database)

为什么最后说数据库呢?因为Room中配置数据库我们需要表和数据访问对象,直接使用上述创建好的SolarTerm表和 SolarTermDao对象:

@Database(entities = [SolarTerm::class], version = 1)
abstract class AppDatabase : RoomDatabase() {//获得数据访问对象abstract fun getSolarTermDao(): SolarTermDao
}

3.2.4、添加节气数据到数据库

这里我们不考虑架构的问题了,仅仅示例在Activity中如何使用数据库(db)及数据访问对象(DAO):

//获取到数据库
val db = Room.databaseBuilder(applicationContext, AppDatabase::class.java, "db_solar_terms").build()//获取到数据访问对象
val solarTermDao = db.getSolarTermDao()//查询所有数据并转换为LiveData类型
val terms = solarTermDao.queryAll().asLiveData()//观察数据变化
terms.observe(this, {var temp = ""for (term in it) {temp += "${term.name} - ${term.time} \n"}Log.e("存储的数据", temp)
})val entityYuShui = SolarTerm(name = "雨水",content = "正月中,天一生水,春始属木,然生木者必水也,故立春后继之雨水。且东风既解冻,则散而为雨矣。",time = "2.18-2.19",mark = "春雨贵如油",imgUrl = "https://cdn.dribbble.com/users/2676519/screenshots/7056971/media/efde75ba876f38cb95ce5b936f481784.jpg?compress=1&resize=1000x750"
)//在线程中操作数据库
Thread {solarTermDao.insert(entityYuShui)
}.start()

在获取节气数据列表的时候我们是用了**asLiveData()**将Flow类型的数据转换为了LiveData类型,然后在activity中直接监听该数据的变化。

然后我们新开线程去操作数据访问对象(注意数据库操作需要在子线程中),添加了一条数据到表中。运行上述代码,在控制台应该会打印出如下日志:

存储的数据: 雨水 - 2.18-2.19

然后我们打开下方App Inspection栏,选中你的设备,稍等片刻后应该就能看到我们创建的了,如下所示:

好了,这个时候我们把日志打印的面板悬浮出来放到了数据库面板的上面。接下来展示一波骚操作,直接更改数据库中表数据,我们把name名更改下,看看有什么效果:

哇哦!这就是Room的强悍之处了,搭配Flow或者LiveData,修改数据库数据后观察者可以直接得到响应。(为什么id是从2开始的呢?因为我之前做实验添加过数据又删了,id是自增的,所以到2了!)

四、Compose + Flow

其实单纯的Room和Compose并没有关系,Flow才是我们要处理的问题,而Flow数据又可以通过 asLiveData() 转换为LiveData数据,又或者通过 collectAsState() 来直接转换为Compose所需的State数据,所以文章到这里就基本结束了,我们只需在之前的代码中将伪数据更改为相应的State数据即可,如下所示:

val termsState = terms.observeAsState(arrayListOf())LazyColumn {items(termsState.value) {SolarTermsItem(entity = it)}
}

眼见为实,最后还是看下效果吧,左侧是AS中数据库的操作,右侧是模拟器上显示的UI:

你自己的增删改查同样会触发更新,这里我就偷懒不再演示了。

五、小结

写了这么一大片文章,其实就是一个Flow转LiveData的 asLiveData() 方法以及Flow转State的 collectAsState() 方法,还有一个图片加载库accompanist-coil。Room这里我们接触的只是冰山一角,还有很多等着我们去学习和探索,加油啊!

以上代码仅仅作为示例使用,代码格式和规范都不敢恭维,万万不可用于开发。

Compose搭档 — Flow、Room相关推荐

  1. 海外直播、聊天交友APP的开发及上架GooglePlay体验【Compose版】

    前言 Jetpack Compose在2021年7月底的时候正式发布了Release 1.0版本,在8月中旬的时候正好赶上公司海外项目计划重构,于是主动请缨向领导申请下来了此次开发的机会.由于之前一直 ...

  2. JS组合函数(Composition):原来如此!

    有时会听到组合函数这个概念,就是到这是高阶函数,函数式编程,特别高大上.但是可能我们都没察觉到,平时一直都在使用它.(本文阅读时间约15分钟) 目录 1. 组合函数是什么? 2. COMPOSE 3. ...

  3. JAVASCRIPT函数组合:有什么大不了的?

    一些人会说,函数组合是某种神圣的真理.一个你应该沉思时卑微地跪下并上香的神圣原则.但函数组合其实并不复杂.不过你是否意识到,你可能一直在使用它.那么为什么函数式编程程序员会对此烦恼呢?它有什么大不了的 ...

  4. 写出高质量代码的10个Tips

    7 条写作原则如下: 让段落成为写作的基本单位,每个段落只说 1 件事情: 省略不必要的词语: 使用主动式: 避免连串的松散句子: 把相关内容放在一起: 多用肯定语句: 善用平行结构: 对应的,在编码 ...

  5. 写出高可读 JS 的 7 条原则

    William Strunk 在 1920 年出版的<The Elements of Style> 一书中列出了写出好文章的 7 条原则,过了近一个世纪,这些原则并没有过时.对于工程师来说 ...

  6. 编码如作文:写出高可读 JS 的 7 条原则

    共 5914 字,读完需 8 分钟.编译自 Eric Elliott 的文章,好的程序员写出来的代码就如同优美的诗赋,给阅读的人带来非常愉悦的享受.我们怎么能达到那样的水平?要搞清楚这个问题,先看看好 ...

  7. Compose学习笔记1-compose、state、flow、remember

    新建一个 compose 项目 开始前,请下载最新版本的 Android Studio Arctic Fox,然后使用 Empty Compose Activity 模板创建应用. 我们先看看在 ap ...

  8. 为什么要在JavaScript中使用静态类型? (使用Flow进行静态打字的4部分入门)

    by Preethi Kasireddy 通过Preethi Kasireddy 为什么要在JavaScript中使用静态类型? (使用Flow进行静态打字的4部分入门) (Why use stati ...

  9. Jetpack Compose学习笔记

    在前不久的 Android Dev Summit '19 上,Jetpack Compose 终于发布了一个可直接获得的预览版.现在的版本还是 0.1.0-dev02,处于非常早期的版本,官方也再三强 ...

最新文章

  1. STE:中科院微生物所胡松年组揭示一年内医院ICU环境菌群的生物多样性
  2. Qt 设置窗口背景图片的几种方法
  3. 深入理解JVM垃圾收集机制,下次面试你准备好了吗
  4. 从大数据到深度学习,这些年度开源“新秀”你可用过?
  5. [leetcode]求数组的第k个最大值,python快排解法
  6. java知识点3(null)
  7. apache配置文件“注解内容”全翻译
  8. Linux中Apache服务器的简单配置
  9. 使用ld的wrap选项替换已有库函数
  10. 数学建模国赛 2020B-穿越沙漠 第一关 Lingo 和 C语言 动态规划求解
  11. 方舟建筑代码指令大全
  12. 应用,传输层协议和端口对应关系
  13. 配方奶粉,尽量不用鲜奶
  14. 英语口语198之每日十句口语
  15. 弘辽科技:数字化衍生菜篮子工程,电商巨头纷纷布局
  16. 一个股市老操盘手的突然感悟
  17. 预测性编码(Predictive Coding)简介
  18. SSRF(Server-side Request Forgery)
  19. 云舒3C,巧解云南电网GIS系统之殇的利刃
  20. 教你如何使用tftpd32烧录内核及文件系统镜像到nand flash

热门文章

  1. pycharm中提示windows找不到文件‘chrome’
  2. ai人工智能相关职业_2020年及以后的5个人工智能最佳职业
  3. 商城开发之商品分类表的设计、使用、管理
  4. 【论文精读】Parallax-tolerant Image Stitching
  5. MyBatis-Plus对于大数据量查询,采用分页查询按批次处理结果,通用工具封装
  6. 华师计算机基础在线作业秋,17秋华师《计算机基础》在线作业 (答案)
  7. 2020链家杭州二手房数据分析(截止到2020年09月07日)
  8. 内存 60 年变迁史
  9. NumPy 和 Pandas 数据分析实用指南:1~6 全
  10. Qt OpenGL 旗帜效果(飘动的纹理)