当前位置: 代码网 > it编程>编程语言>Java > 2024年最新Kotlin flow实践总结_flow combine(1),头条hr面试

2024年最新Kotlin flow实践总结_flow combine(1),头条hr面试

2024年07月28日 Java 我要评论
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。需要这份系统化的资料的朋友,可以戳这里获取一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!}coldFlow onStart, thread:maincoldFlow onCompletion, thread:maincoldFlow colle

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

一个人可以走的很快,但一群人才能走的更远!不论你是正从事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


### 场景三:多种数据源,按照顺序合并进行展示


![image.png](https://img-blog.csdnimg.cn/img_convert/9abbe46082c8bf48d57b81cb8bf41c1f.png#pic_center)


在实际的开发场景中,经常一个页面的数据,是需要发起多个网络请求之后,组合数据之后再进行显示。 比如类似这种页面,3种数据,需要由3个网络请求获取得到,然后再进行相应的显示。


实现目标:


1. 接口间不需要互相等待,哪些数据先回来,就先展示哪部分
2. 控制数据的显示顺序


##### flow combine操作符


可以合并多个不同的 flow 数据流,生成一个新的流。 只要其中某个子 flow 数据流有产生新数据的时候,就会触发 combine 操作,进行重新计算,生成一个新的数据。


##### 例子



class homeviewmodel : viewmodel() {

//暴露给view层的列表数据

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!


img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

8910224b259a5ffe804fa6d0db.png)
[外链图片转存中…(img-lurofabf-1715707904369)]
[外链图片转存中…(img-9y1ln3ol-1715707904369)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com