2022-12-10分享 回调-协程-观察者模式-SVN分支管理-缓存思考
最近开发Android中遇到的一些技术点的总结。
回调
同步
我们比较熟悉的编程模式就是同步,调用A函数后,等待A函数结束后返回结果给B函数进行处理。
|
|
这就是函数的同步调用,顺序执行。handle(res)的调用必须等待request()的完成。
异步
针对上面的例子,由于request请求返回的不可预见性,我们不想去等待request()的返回,直接去调用other(),这就是异步。
异步最常见的案例就是回调函数。
回调
那么对于异步的任务来说,我们想让request()请求完成后,直接去调用handle(res)方法,这时候就可以用到回调函数。
|
|
回调就是A函数和B函数,在A的某一个环节需要B自己告诉A怎么做,这就是回调。例如去商店里买东西,暂时缺货,留下电话号码就是一个回调函数,东西来货了,店员打电话通知就是一个调用回调函数。
最经典的一个理解就是 don’t call me, I’ll call you.
实际案例
在Android开发中,大量使用到了回调函数,比较经典的案例就是网络请求的调用。app作为一个进程存在于Android系统中,其可以存在多个线程,其中有一个主线程,也叫UI线程负责整个app的UI绘制。那么对于UI线程来说,一旦存在耗时操作,如网络请求调用,那么UI线程就会被阻塞,导致UI的绘制停滞。
所以在UI线程中,不能有耗时的操作出现,那么上述的回调函数就可以很好的解决这个问题。
- 首先我们定义一个回调函数的接口,这个接口定义在请求完成后需要做的操作。
|
|
- 其次我们定义好请求的方法,并且在传参中加入上面定义好的回调接口。
|
|
- 最终我们在执行请求的同时去补全我们的回调逻辑
|
|
协程
回调解决了异步调用的问题,但是异步回调同样存在问题,原本统一的逻辑流拆分开了,有可能会产生回调地狱的现象,毁掉里面嵌套回调。同时上下文也在一直改变了,需要去手动维护上下文,也就是手动维护状态。
|
|
|
|
除此之外,无论是代码的阅读还是后期维护的复杂度都要比同步要高。
如果既不想要阻塞,又想要逻辑流的统一,我们可以使用协程。
我们都知道线程,在实际的开发中也经常用多线程,线程是操作系统的资源,调度也是由操作系统来完成的。
协程是比线程更细粒度的调度单位,可以理解为一个任务,一个人干了百分之二十,然后去干其它任务,其它任务结束后,继续回来干剩余的百分之八十的任务。
|
|
目前,Python,Kotlin,JS,Go等语言都支持协程,Java19中也提供了虚拟线程的功能。
观察者模式
在Android开发中,观察者模式是比较常见的一种设计模式。
观察者模式是一种行为设计模式, 允许你定义一种订阅机制, 可在对象事件发生时通知多个 “观察” 该对象的其他对象。https://refactoringguru.cn/design-patterns/observer
具体代码实现:
java.util里已经完成了观察者模式。
- Observable: 被观察者,管理观察者,并给观察者发送消息通知改变
- Observer: 观察者,被观察者发送通知给观察者,观察者进行改变
实际应用
- Android广播机制的实现,定义广播,注册广播的接受者,当有广播发送的时候,推送给所有的接收者。
- Android回调接口的实现,只有一个观察者的观察者模式。
Java案例
被观察者消费一份数据,如果有多个业务需要的话,分发给所有的观察者。
责任链模式案例
使用阈值校验健康码,核酸,体温等。如果使用正常逻辑代码编写,情况可能会是下面这样:
|
|
这样的代码比较直观,能够一眼看出来意图。但是后期如果在增加新的条件,那么就可能需要继续进行嵌套if,维护成本大大增加,这种情况下也可以使用责任链模式去校验,如果某个条件不成立,则退出判断。
SVN分支管理
在写数字哨兵联通版的时候遇到这样一个svn的使用问题,现场已经存在一个稳定的开发分支,当前提出来要进行开发人脸的版本,那么如果我继续在当前开发分支上进行开发,那么后续如果现场有问题需要修改,则需要大量注释当前开发的人脸的版本。势必会在效率和准确度方面存在一些问题。
这个时候就可以尝试利用和git一样的分支管理,svn的分支和git的分支类似,拥有一个类似于master分支的trunk分支,作为主分支,可以在主分支上拉branches, 作为开发分支,在开发完毕后,可以将开发分支的代码合并到主分支上。
缓存的一些尝试和思考
业务上经常需要缓存数据,基本上都是点位信息,一般都是直接放到内存中,然后加定时任务。目前我感觉主要有以下几点不便:
- 定时任务更新需要手动触发,可以在定制任务上写接口,技术操作不便
- 数据在内存中,可见性较低
- 维护的话,缺少某一类数据需要重新复制粘贴