不是因为看到希望才坚持,而是因为坚持了才会有希望!
场景
在做直播软件的时候,需要在用户打开App后,先后弹出签到,活动,提示等一系列弹窗。每个弹窗都要在前一个弹窗消失后弹出。于是就面临一个弹窗顺序问题,那时候对设计模式很陌生,不知道怎么更好的解决弹窗顺序问题,都在下前一个弹窗取消或关闭时去加载后面一个弹窗。这样做虽然也能解决问题,但是实现并不优雅,如果在弹窗中间再添加一个其他类型的弹窗改动代价就变得很大,特别是当你是后来接手代码的新人,稍有不慎,就要背锅。怎么能简单而又优雅的解决这个问题呢?
思路
开发者必读的23种设计模式,对于日常开发问题的解决提供了很好的思路,可以说几乎所有的优秀架构都离不开设计模式,这也是面试必问问题之一。23种设计模式中有一个责任链模式,为弹窗问题提供了解决方案,这也是我从okhttp源码中学习到的,读过okhttp的同学都知道,okhttp网络请求中的五大拦截器基于链式请求,使用起来简单高效。本篇文章同样也是基于责任链的思路来解决弹窗顺序问题。(如果对Okhttp源码还不了解的同学,请查看这篇文章《源码解析之OkHttp五大拦截器原理解析》)
代码
- 首页我们定义一个接口DialogIntercept,同时提供两个方法 intercept和show。
interface DialogIntercept {
fun intercept(dialogIntercept: DialogChain)
fun show():Boolean
}
所有的弹窗都需要实现DialogIntercept中的这两个方法。
- 自定义弹窗实现DailogIntercept接口。
● 弹窗
class FirstDialog(val context: Context) :DialogIntercept{
override fun intercept(dialogIntercept: DialogChain) {
}
override fun show():Boolean{
return true
}
}
这里show()方法默认返回true,可根据业务逻辑决定弹窗是否显示。
- 提供一个弹窗管理类DialogChain,通过建造者模式创建管理类。根据弹窗添加的顺序弹出。完整代码如下:
class DialogChain(private val builder: Builder) {
private var index = 0
fun proceed(){
when(index){
in builder.chainList.indices ->{
val dialogIntercept = builder.chainList[index]
if (dialogIntercept.show()){
dialogIntercept.intercept(this)
}else{
builder.chainList[++index].intercept(this)
}
index++
}
builder.chainList.size->{
builder.chainList.clear()
index = 0
}
}
}
class Builder(){
var chainList:MutableList<DialogIntercept> = mutableListOf()
fun addIntercept(dialogIntercept: DialogIntercept):Builder{
if (!chainList.contains(dialogIntercept)){
chainList.add(dialogIntercept)
}
return this
}
fun build():DialogChain{
return DialogChain(this)
}
}
}
效果
为了测试效果,分别定义三个弹窗,FirstDialog,SecondDialog,ThirdDialog。按照显示顺序依次添加到DialogChain弹窗管理类中。
- 定义弹窗。
由于三个弹窗代码基本相同,下面只提供FirstDialog代码。
class FirstDialog(val context: Context) :DialogIntercept{
override fun intercept(dialogIntercept: DialogChain) {
show(dialogIntercept)
}
override fun show():Boolean{
return true
}
private fun show(dialogIntercept: DialogChain){
AlertDialog.Builder(context).setTitle("FirstDialog")
.setPositiveButton("确定"
) { _, _ ->
dialogIntercept.proceed()
}.setNegativeButton("取消"
) { _, _ ->
dialogIntercept.proceed()
}.create().show()
}
}
2 . 分别将三个弹窗按照显示顺序添加到管理器中,执行proced方法显示。
DialogChain.Builder()
.addIntercept(FirstDialog(this))
.addIntercept(SecondDialog(this))
.addIntercept(ThirdDialog(this))
.build().proceed()
总结
再优秀的架构,都离不开设计模式和设计原则。很多时候我们觉得架构师遥不可及,其实更多的时候是我们缺少一个想要进步的心。新的一年,新的起点,新的开始。
如果你看到了这里,觉得文章写得不错就给个赞呗?更多Android进阶指南 可以扫码 解锁更多Android进阶资料
1、《Android性能优化实战篇》
2、《音视频精编源码解析》
3、24种设计模式介绍与6大设计原则
4、360°全方面性能调优
5、2021最新版数据结构与算法面试题手册 1
6、2023年Android中高级最全面试真题答案解析
7、Android Compose 强化实战
8、Android Framework 源码开发揭秘(2)
9、Android Jetpack Compose开发应用指南第三版
10、Android 音视频开发进阶指南-无水印(1)
11、Android车载操作系统开发揭秘
12、Android车载系统应用指南(1)
13、Android多媒体应用开发实战详解:图像、音频、视频、2D和3D-2
14、Android高级UI开源框架进阶解密(1)无水印版
15、Android源码解析(1)
16、Flutter技术解析与实战
17、Flutter技术进阶
18、Flutter入门与实战 无水印
19、Flutter完整开发实战详解
20、Jetpack架构组件从入门到精通
21、KMM跨平台框架入门教程无水印
22、Kotlin 入门教程指南(1)
23、kotlin从入门到精通
24、高级Android插件化强化实战(附源码)
25、高级Android组件化强化实战(附源码)
26、高级Jetpack强化实战
27、高级Kotlin强化实战(附Demo)
28、鸿蒙零基础入门学习指南
29、史上最详android版kotlin协程入门进阶实战指南
30、音视频开发教程(附面试题)
敲代码不易,关注一下吧。ღ( ´・ᴗ・` )