闲谈针对JetPack搭配设计模式构建一个简易通用的MVVM

文章目录

  • 闲谈针对JetPack搭配设计模式构建一个简易通用的MVVM
    • 论设计模式的重要性
      • 使用代理模式解决统一显示LoadingDialog的问题
    • 论JetPack的重要性
      • 动态请求权限
      • 利用lifecycle去感知项目页面的生命周期完成一些特殊的组件。
    • 抽象封装MVVM为Activity、Fragment提供基类
      • 构建Activity及Fragment共用IPageCommonAction
      • IBaseVM
      • 针对页面的抽象设计
    • 总结

闲谈针对JetPack搭配设计模式构建一个简易通用的MVVM

在经过最近一段时间的工作经历加深了我对设计模式的一个重要性的理解。事情的起因在于,最近半年多换了转进一个新的项目组去维护迭代一个项目App。在这个项目中我发现了一个严重的问题,由于项目基本采用了MVVM的方式来作为解耦,但是由于前期不存在有明确的分工去构建一些基类的构建。导致一个很简单的基类Fragment、DialogFragment、Activity存在着四五种不同程度封装而且都没有写好。甚至连一些需要基于页面的生命周期的组件都没有管理好,譬如使用了华为的二维码扫码功能开放组件,每处使用的UI样式以及构建都大量使用了重复代码。导致研发效率低下的一个问题。面对这种问题我采用了在这里我给出我的一套思维方案:

论设计模式的重要性

使用代理模式解决统一显示LoadingDialog的问题

为什么说代理模式很重要。代理是具有一个可做可不做的思维模式。你可以这样设想。A、B产品都是能提供具有一定功能及作用。但是在于如果一个解决方案定型了使用A或者B的时候就会建立强绑定关系后续更换往往容易会出现大代价。为了解决产品迭代的,根据需求能够简单快捷的替换全局加载弹窗甚至可以某个页面自定义加载弹窗,统一使用代理方式去实现解耦。

实现
CommonLoadingProxyV1
«interface»
LoadingProxy
+showLoading(FragmentManager,tag)
+hideLoading()

论JetPack的重要性

JetPack作为Android新一代官方组件技术,其目的通过新一代的技术方案或者接口接口去解决以往的一些Android开发的痛点。接下来我会重点讲解我是如何利用这些去解决一些常见问题

动态请求权限

首先设想一下,如果App不进行一个动态权限申请,总是在当前页面启动时或者启动页面的时候就进行权限,往往容易存在一个弊端,闪退的bug。接下来请看如何闪退

启动页/当前页 权限成功要做的业务 权限失败要做的业务 app进入后台 用户or系统关闭权限 OnCreate时请求权限成功 请求权限失败 权限请求成功后因为一些不可控因素App进入后台 权限被回收 回到页面时大概率闪退 启动页/当前页 权限成功要做的业务 权限失败要做的业务 app进入后台 用户or系统关闭权限

那么针对现有项目容易出现这样的一个问题我是这样解决的

首先利用ActivityResultLauncher构建动态权限申请,并提供相应的成功以及失败的回调并且提供一个重试机制,期望图如下

Activity/Fragement IPermissionHelper IPermissionChecker IPermissionRetry 根据生命周期注册权限申请回调 请求权限 内部处理权限是否请求成功 请求权限成功 请求权限失败是否重试 需要重试重新请求权限 重试请求权限 请求权限成功 请求权限成功 请求权限失败是否重试 不重试请求权限或重试次数达到最大返回失败 请求权限失败 请求权限失败 根据生命周期解绑权限申请回调 Activity/Fragement IPermissionHelper IPermissionChecker IPermissionRetry

基于上诉思路,这样去构建实现:

抽象类图关系:

引用
引用
«interface»
IPermissionHelper
fun requestSinglePermission(String,retryTime:Int?=null,ISinglePermissionCheckAction.()
fun requestMultilPermission(Array,retryTime:Int?=null,call: IMultilplePermissionCheckAction.()
fun attach(activity: ComponentActivity)
fun attach(fragment: Fragment)
fun detach(activity:ComponentActivity)
fun detach(fragment:Fragment)
«interface»
ISinglePermissionCheckAction
fun checkAction(result: Boolean)
var okAction:(()
var failAction:(()
«interface»
IMultilplePermissionCheckAction
fun checkAction(map: Map)
var okAction:(()
var failAction:((List)

IPermissionChecker 类图实现关系

实现
实现
实现
实现
NormalSinglePermissionChecker
«interface»
ISinglePermissionCheckAction
fun checkAction(result: Boolean)
var okAction:(()
var failAction:(()
RetrySinglePermissionChecker
+retryMaxTime
-currentRetryTime
override fun checkAction(result: Boolean)
NormaMultilplePermissionChecker
«interface»
IMultilplePermissionCheckAction
fun checkAction(map: Map)
var okAction:(()
var failAction:((List)
RetryMultilplePermissionChecker
+retryMaxTime
-currentRetryTime
override fun checkAction(map: Map)

IPermissionHelper 类图实现关系

实现
SupportPermission
-ActivityResultLauncher?
-ActivityResultLauncher>?
-ActivityResultCallback>
-ActivityResultCallback
-IMultilplePermissionCheckAction
-ISinglePermissionCheckAction
IPermissionHelper

利用lifecycle去感知项目页面的生命周期完成一些特殊的组件。

为什么用lifecycle去感知页面生命周期。

例如利用华为开源组件实现手机扫码功能,并针对当前识别到的二维码进行判断是否有效,针对有效的二维码实现相应的业务逻辑。

但是上诉的开源组件需要和页面的生命周期进行绑定,避免出现问题。为了减少页面的重写生命周期回调模板代码,可以利用实现LifecycleEventObserver生命事件回调接口在里面处理相应事件,譬如那么仅仅实现这样的时序关系:

页面 扫码组件的配置参数 扫码组件View 配置扫码组件需要的配置 设置配置参数 初始化扫码组件并绑定生命周期 执行扫码 扫码过程执行正确回调流程 检测到二维码 检测的二维码业务判断 二维码正确 二维码正确停止扫码 回调正确的二维码 二维码结果回调 扫码过程重试 检测到二维码 检测的二维码业务判断 二维码不正确 重新扫码 页面 扫码组件的配置参数 扫码组件View

大致实现如下:

实现
构建配置参数
利用ScannerViewConfig进行生命周期绑定
控制启动或者结束扫码
ScannerView
LifecycleEventObserver
page
ScannerViewConfig
-lifecycle: Lifecycle
-judgeScannerResultAction:((String)
-actualResultAction:((String)

抽象封装MVVM为Activity、Fragment提供基类

构建Activity及Fragment共用IPageCommonAction

IPageCommonAction主要用于封装 BaseActivityBaseFragment共用组件

«Interface»
IPageCommonAction
Boolean inputMethodOptimizeStatus
IPermissionHelper permissionHelper
LoadingProxy loadingProxy
T? binding
VM?: vm
LifecycleOwner requestLifecycleOwner()
Int getContentLayoutRes()

IBaseVM

IBaseVM 代表ViewModel抽象设计

在页面中有可能存在需要一个或多个VM去实现相应的业务逻辑,那么我们可以这样的抽象去设置我们的VM接口

实现
实现
«interface»
SingleBaseVM
«interface»
IBaseVM
«interface»
MutlitpeBaseVM

针对页面的抽象设计

继承
实现
实现
继承
«class»
BaseFragment
Fragment
«interface»
IPage
Int getContentLayoutRes()
showToast(String)
safeInitView()
IPageCommonAction getCommonAction()
«class»
BaseActivity
AppCompatActivity

总结

尽可能使用抽象思维去构建项目,这样外部使用以及开发仅仅需要调用方法即可,甚至可以基于抽象方法的重写,去实现对应的业务逻辑以及迭代功能,以抽象应对多变化。但是记住一点没有永远的架构以及构建,有得只是适合当下的构建以及方法而已。不要为了一件事让代码陷入一个牛角里面去。

你可能感兴趣的:(设计模式,android,android,jetpack,MVVM)