网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事it行业的老鸟或是对it行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
mbinding.tvloadingstatus.text = "加载中"
}.onempty {
log.d(tag, "coldflow onempty, thread:${thread.currentthread().name}")
mbinding.progressbar.isvisible = false
mbinding.tvloadingstatus.text = "数据加载为空"
}.catch {
log.d(tag, "coldflow catch, thread:${thread.currentthread().name}")
mbinding.progressbar.isvisible = false
mbinding.tvloadingstatus.text = "数据加载错误:$it"
}.oncompletion {
log.d(tag, "coldflow oncompletion, thread:${thread.currentthread().name}")
mbinding.progressbar.isvisible = false
mbinding.tvloadingstatus.text = "加载完成"
}
//指定上游数据流的coroutinecontext,下游数据流不会受到影响
.flowon(dispatchers.main)
.collect {
log.d(tag, "coldflow collect:$it, thread:${thread.currentthread().name}")
}
}
}
比如上面的例子。 使用flow构建起函数,创建一个冷流,3秒后发送一个值到数据流中。 使用onstart,onempty,catch,oncompletion操作符,监听数据流的状态。
日志输出:
coldflow onstart, thread:main
coldflow oncompletion, thread:main
coldflow collect:1, thread:defaultdispatcher-worker-1
### 场景二:同一种数据,需要加载本地数据和网络数据
在实际的开发场景中,经常会将一些网络数据保存到本地,下次加载数据的时候,优先使用本地数据,再使用网络数据。
但是本地数据和网络数据的加载完成时机不一样,所以可能会有下面几种场景。
1. 本地数据比网络数据先加载完成:那先使用本地数据,再使用网络数据
2. 网络数据比本地数据先加载完成:
* 网络数据加载成功,那只使用网络数据即可,不需要再使用本地数据了。
* 网络数据加载失败,可以继续尝试使用本地数据进行兜底。
3. 本地数据和网络数据都加载失败:通知上层数据加载失败
#### 实现cacherepositity
将上面的逻辑进行简单封装成一个基类,cacherepositity。
相应的子类,只需要实现两个方法即可。
* cresult:代表加载结果,success 或者 error。
* fetchdatafromlocal(),实现本地数据读取的逻辑
* fetchdatafromnetwork(),实现网络数据获取的逻辑
abstract class cacherepositity {
private val tag = “cacherepositity”
fun getdata() = channelflow<cresult<t>> {
supervisorscope {
val datafromlocaldeffer = async {
fetchdatafromlocal().also {
log.d(tag,"fetchdatafromlocal result:$it , thread:${thread.currentthread().name}")
//本地数据加载成功
if (it is cresult.success) {
send(it)
}
}
}
val datafromnetdeffer = async {
fetchdatafromnetwork().also {
log.d(tag,"fetchdatafromnetwork result:$it , thread:${thread.currentthread().name}")
//网络数据加载成功
if (it is cresult.success) {
send(it)
//如果网络数据已加载,可以直接取消任务,就不需要处理本地数据了
datafromlocaldeffer.cancel()
}
}
}
//本地数据和网络数据,都加载失败的情况
val localdata = datafromlocaldeffer.await()
val networkdata = datafromnetdeffer.await()
if (localdata is cresult.error && networkdata is cresult.error) {
send(cresult.error(throwable("load data error")))
}
}
}
protected abstract suspend fun fetchdatafromlocal(): cresult<t>
protected abstract suspend fun fetchdatafromnetwork(): cresult<t>
}
sealed class cresult {
data class success(val data: t) : cresult()
data class error(val throwable: throwable) : cresult()
}
#### 测试验证
写个testrepositity,实现cacherepositity的抽象方法。
通过delay延迟耗时来模拟各种场景,观察日志的输出顺序。
private fun cachereposititydemo(){
val repositity=testrepositity()
lifecyclescope.launch {
repositity.getdata().onstart {
log.d(tag, “testrepositity: onstart”)
}.oncompletion {
log.d(tag, “testrepositity: oncompletion”)
}.collect {
log.d(tag, “collect: $it”)
}
}
}
##### 本地数据比网络数据加载快
class testrepositity : cacherepositity() {
override suspend fun fetchdatafromlocal(): cresult {
delay(1000)
return cresult.success(“data from fetchdatafromlocal”)
}
override suspend fun fetchdatafromnetwork(): cresult<string> {
delay(2000)
return cresult.success("data from fetchdatafromnetwork")
}
}
模拟数据:本地加载delay1秒,网络加载delay2秒
日志输出:collect 执行两次,先收到本地数据,再收到网络数据。
onstart
fetchdatafromlocal result:success(data=data from fetchdatafromlocal) , thread:main
collect: success(data=data from fetchdatafromlocal)
fetchdatafromnetwork result:success(data=data from fetchdatafromnetwork) , thread:main
collect: success(data=data from fetchdatafromnetwork)
oncompletion
##### 网络数据比本地数据加载快
class testrepositity : cacherepositity() {
override suspend fun fetchdatafromlocal(): cresult {
delay(2000)
return cresult.success(“data from fetchdatafromlocal”)
}
override suspend fun fetchdatafromnetwork(): cresult<string> {
delay(1000)
return cresult.success("data from fetchdatafromnetwork")
}
}
模拟数据:本地加载delay 2秒,网络加载delay 1秒
日志输出:collect 只执行1次,只收到网络数据。
onstart
fetchdatafromnetwork result:success(data=data from fetchdatafromnetwork) , thread:main
collect: success(data=data from fetchdatafromnetwork)
oncompletion
##### 网络数据加载失败,使用本地数据
class testrepositity : cacherepositity() {
override suspend fun fetchdatafromlocal(): cresult {
delay(2000)
return cresult.success(“data from fetchdatafromlocal”)
}
override suspend fun fetchdatafromnetwork(): cresult<string> {
delay(1000)
return cresult.error(throwable("fetchdatafromnetwork error"))
}
}
模拟数据:本地加载delay 2秒,网络数据加载失败
日志输出:collect 只执行1次,只收到本地数据。
onstart
fetchdatafromnetwork result:error(throwable=java.lang.throwable: fetchdatafromnetwork error) , thread:main
fetchdatafromlocal result:success(data=data from fetchdatafromlocal) , thread:main
collect: success(data=data from fetchdatafromlocal)
oncompletion
##### 网络数据和本地数据都加载失败
class testrepositity : cacherepositity() {
override suspend fun fetchdatafromlocal(): cresult {
delay(2000)
return cresult.error(throwable(“fetchdatafromlocal error”))
}
override suspend fun fetchdatafromnetwork(): cresult<string> {
delay(1000)
return cresult.error(throwable("fetchdatafromnetwork error"))
}
}
模拟数据:本地数据加载失败,网络数据加载失败
日志输出: collect 只执行1次,结果是cresult.error,代表加载数据失败。
onstart
fetchdatafromnetwork result:error(throwable=java.lang.throwable: fetchdatafromnetwork error) , thread:main
fetchdatafromlocal result:error(throwable=java.lang.throwable: fetchdatafromlocal error) , thread:main
collect: error(throwable=java.lang.throwable: load data error)
oncompletion
### 场景三:多种数据源,按照顺序合并进行展示

在实际的开发场景中,经常一个页面的数据,是需要发起多个网络请求之后,组合数据之后再进行显示。 比如类似这种页面,3种数据,需要由3个网络请求获取得到,然后再进行相应的显示。
实现目标:
1. 接口间不需要互相等待,哪些数据先回来,就先展示哪部分
2. 控制数据的显示顺序
##### flow combine操作符
可以合并多个不同的 flow 数据流,生成一个新的流。 只要其中某个子 flow 数据流有产生新数据的时候,就会触发 combine 操作,进行重新计算,生成一个新的数据。
##### 例子
class homeviewmodel : viewmodel() {
//暴露给view层的列表数据
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
8910224b259a5ffe804fa6d0db.png)
[外链图片转存中…(img-lurofabf-1715707904369)]
[外链图片转存中…(img-9y1ln3ol-1715707904369)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
发表评论