Android 业务逻辑应该如何写(第二篇)

Android 业务逻辑应该如何写(第一篇)

Android 业务逻辑应该如何写(第二篇)(本文)

View的组织形式

再次重复一次:何为view的组织形式呢,简单点解释也就是用一种什么样的方法将各个view组合成一个完整的页面,当然把所有的view都堆积在一个 xml里面,也是一种方法,只不过这样的话你的xml会超过几千行哦

先抛出一个问题,如下图为抖音的推荐流, 如果你是抖音的开发者,你将如何编写该页面的View

我妄自揣测一下:

A 同学:这个页面不就几张图片:"头像"、"点赞"、"评论"、"收藏"、"不喜欢"、"分享"、"音乐转盘",

以及几个文案:"用户名"、"视频简介"、"相关搜索信息",然后再加上一个广告的图片和相关文案。

这几个view通过各种布局摆放在一个xml中,然后通过ViewModel进行逻辑处理,Livedata通知ui更新。

对于评论弹窗我直接单独一个Fragment就解决了。

B 同学: 我可以把 "头像"、"点赞"、"评论"、"收藏"、"不喜欢"、"分享"、"音乐转盘"等信息用一个自定义view给封装起来,在主xml中写入自定义view和其他view元素,这样可以将一些复杂的view拆分一点。然后再通过MVVM或者MVP等混合形式来进行数据通信和view的更新。

对于评论弹窗可以用BottomSheetDialog或者BottomSheetDialogFragment。

其实没有什么标准或者正确答案,但一个健壮、高效率、易扩展的View框架的基本思想都大同小异。

先分享其他两个大厂他们的View业务框架是怎么样的

小红书

time.geekbang.org/qconplus/de...

极客时间上小红书的分享,可能需要开通超级会员才可以看(我这里不是在推销大家买会员哦~)

微博

微博相关的分享是很早了,2018年,本来是一个完整的ppt,但是掘金这里无法插入ppt附件,我把网盘的链接放到这里,感兴趣的同学可以下载看看。 【超级会员V7】通过百度网盘分享的文件:议题十四 微博信... 链接:pan.baidu.com/s/1Qhv-p3KA... 提取码:7w7z】

在正文我将与本文主题相关的ppt页面粘贴在下方,方便大家查看

回到原问题

看完上面两个大厂的案例,我们每个人可能都会有自己的思考,或清晰、或模糊、但可能也会疑问:

一个页面的逻辑编写用得着这么复杂吗!

是的

一个巨量app他就是这么复杂。在一个页面中,包含着你看的见元素,也包括看不见的 埋点 、实验、以及还未被触发业务。同时一个页面中的所有元素,不见得属于一个模块、更甚至开发的同学都不是一个组,都没见过面(公司内网友)。这些不同模块间View的通信,不同开发同学的代码风格(亦或者技术水平的参差)等都会导致代码bug过多、开发效率低下,以及后续想要对某个业务优化或者调整都将会有很大的挑战。

所以才需要一个"精美"的View框架去让业务代码变的更加"轻快"。

写到这里感觉要即将推出一款新的开源框架似的,不过本文还是注重其思想吧(大家也可以理解成嘴炮)

直接先推荐一个现成的开源框架吧【github.com/kaleai/Shat...

这个不是我写的~是找了一个思想差不多,并且很优秀的一个开源框架【kaleai/Shatter】,有兴趣的可以体会下

再重新回到本节的首个问题。

B 同学的思路可能稍微先进了一些,他有意识的将复杂view进行拆分,然后再组合。

拆分和组合 是我想要着重表达的。

拆分和组合 也是一个好的View框架的基础。

在这个基础之上,可能我们还需要考虑以下几点:

  • View之间的通信问题,包括业务状态以及数据的通信

  • View对Activity或Fragment生命周期的感知

  • View的复用、异步加载、预加载、懒加载等有关性能的问题

View的 拆分和组合

还是以抖音的推荐页面为例,我们将对此进行拆分

和【github.com/kaleai/Shat... 框架一样,我们也有一个LightFragment。该LightFragment拥有和原生Fragment几乎一样的能力

  • 包括它(LightFragment)是一个view的承载容器
  • 它拥有和Fragment一样的生命周期
  • 同样的它也有业务逻辑(你也可以使用mvvm等框架,将业务逻辑写到Viewmodel中,但又因为该LightFragment 中的业务足够单纯和轻量,也可以写成mvc模式)

同时该LightFragment也有原声Fragment没有的能力

  • 它底层打通了所有LightFragment之间的通信(这里好像小米的新系统-Xiaomi HyperOS中提到的万物互联)
  • 它还实现了对View加载优先级的定义,可以满足view的预加载、懒加载、甚至在子线程(子线程只是不能更新ui,加载一个view还是可以的),跨页面的加载

同时 LightFragment 又像是ViewGroup和View一样,可以像 ViewGroup.addView 一样,添加子View

这就是我们所定义的 LightFragment

它可以将业务分为无数个LightFragment,同时也可以通过addLightFragment,将各个LightFragment组合成不同的页面。

就像上图所示,我们将可以把整个页面分为【上】【下】【左】【右】【中】五大区域,比如对于【右】区域,我们命名 RightRegionFragment, 然后 RightRegionFragment 又包括 【 头像 Fragment】、【喜欢Fragment】、【评论Fragment】等等。再比如播放器View【VideoFragment】应该在view层级的最底层,我们可以通过 LightFragmentManager. addLightFragment 将页所有的LightFragment组合起来,其中父LightFragment再通过 addLightFragment 把子LightFragment传起来。

这就是View的拆分和组合。

View之间的通信问题,包括业务状态以及数据的通信

我们将所有的业务都细分拆到了各个 LightFragment, 但是实际业务开发中 ,各个 LightFragment并不是独立的 。我们依然拿下面两个图的例子来说明。

第一张图的左侧有【用户名字 (UsernNameFragment )】和【视频简介(VideoIntroductionFragment )】两个信息。第二种图【UsernNameFragment 】和【VideoIntroductionFragment 】没有了,【广告卡片(adCradFragment)】信息出来了。

那么这三个LightFragment(UsernNameFragment、VideoIntroductionFragment、adCradFragment) 就必须相互知道各自的状态。当adCradFragment 要出来的时候,就要通知其他两个LightFragment消失,反之亦然。

问题来了,要通过什么样的方式进行各个LightFragment通信呢?

  • 通过全局的ViewModel和LiveData ?

这确实是一种方式,不过还是觉得有点重,如果业务通信很多,那么要重复写很多LiveData吧,并且LiveData只是一个UI数据保存的工具,切不可当作事件通知工具,这点相信会有很多同学误解

最重要的是:如果用着用形式,我们应该把ViewModel和LiveData写到哪里呢?要知道实际业务开发中LightFragment 可能存在于各个不同的模块中 甚至如果app是基于内插件,那么LightFragment也可能会分散到各个插件中,所以想要在各个地方拿到同一个自定义的ViewModel或LiveData似乎是一个很复杂的事情。不可取!

  • 通过EventBus?

    EventBus我本身就不会推荐去使用,我甚至认为经常使用EventBus的同学是一种偷懒的行为,还有类似发明的LiveDataBus,这些通信工具太过于强大,过于解耦,太多了会导致不可控。

  • 通过的接口、单例也不太行,缺点太明显了

  • 最后选择了Rxjava

实现思路我们把所有的数据或者事件都先发送给大总管LightFragmentManager, 在通过LightFragmentManager 中转给各个子LightFragment

所以,如果想要 发送/获取 某个状态或数据,就可以通过LightFragmentManager来保存和分发

View对Activity或Fragment生命周期的感知

大家应该都LeakCanary吧, 它是如何监控Activity以及Fragment的生命周期的,我们的LightFragment就是如何监控的,不同的是实际上是LightFragmentManager 来进行监控的,然后再将获取到的各个状态分发给其他子LightFragment。

LightFragmentManager 很重要 就是用来保存并主动分发(Rxjava)数据和状态的。同时也是创建View树的起点

View的复用、异步加载、预加载、懒加载等有关性能的问题

这个话题其实有点大

View的复用

这里具体来说是LightFragment的复用

说到view的复用,可能最先想到的是RecycleView,RecycleView的最核心的能力就是对view的复用能力,当然也包括view所对应的业务逻辑代码的复用。

  • 同样的,除来在RecycleView中。我们的其他业务也可能会用到,比如在A页面有用户名字的展示【UsernNameFragment 】,在B页面也有【用户名字】的展示,我们就可以直接拿到现成的UsernNameFragment就添加到B页面就可以了,有关【用户名字】的点击、展示逻辑,甚至埋点都不用写。
  • 再比如大型app会有很多实验,对不同的元素在不同的实验分组下有不同的ui或逻辑,我们就可以直接写两个相关的LightFragment,避免在一个类中写很多if-else来区分实验逻辑。
  • 再比如有些业务需要回退、下线。我们如果直接revert代码的话,可能会造成很多冲突,解冲突又可能会出现bug,耗时费力不讨好。如果选择手动删除代码的话,也会有类似问题。如果有了LightFragment,我们就可以精准的找到需要删除、下线的LightFragment,几乎不用怎么测试。

当然上面所提到了例子,有同学可能认为这不是view的复用,嗯呢写到这里我也觉得起名view的复用似乎不太合适,就先这样吧。

异步加载

这里指LightFragment中view在子线程中加载

关于view在子线程中加载话题会更大,这里就暂时不展开了,后续会单独开一小节来讲述。

预加载、懒加载

写到这里已经深夜2点12分了,脑子开始偷懒了,想要快速结束本节,就把预加载、懒加载一起写了吧

在业务中,有些view的展示优先级比较高,就拿抖音feed流来说,用户信息等view等元素一定是最重要的,这些元素不能懒加载,甚至为了视频滑动更流畅、高优先级的view展示的更快,我们对各个view(LightFragment )做了优先级,高优先级的LightFragment 会提前或正常加载。

在比如有些广告转化卡片,它的出现是有时机的,比如需要时间播放到第5秒时,弹出广告转化卡片,那么对于此类LightFragment我们不必着急的去加载它,也就是懒加载,可以在程序运行中动态加载各个LightFragment。

最好思考(规划):我们可不可以利用LightFragment 由服务端来控制我们的ui展示样式,也就是客户端和服务端先定义好各个LightFragmentkey值,由服务端通过下发不同的key值的顺序来决定端上ui展示的样式呢?

相关推荐
OkeyProxy6 小时前
設置Android設備全局代理
android·代理模式·proxy模式·代理服务器·海外ip代理
刘志辉6 小时前
vue传参方法
android·vue.js·flutter
SteveCode.8 小时前
高性能微服务架构:Spring Boot 集成 gRPC 实现用户与订单服务即时交互
spring boot·微服务·架构
m0_728647088 小时前
Feed流系统重构:架构篇
重构·架构
前期后期9 小时前
Android OkHttp源码分析(一):为什么OkHttp的请求速度很快?为什么可以高扩展?为什么可以高并发
android·okhttp
java_heartLake9 小时前
微服务中间件之Nacos
后端·中间件·nacos·架构
_.Switch10 小时前
构建现代应用的Python Serverless架构详解
运维·开发语言·python·云原生·架构·serverless·restful
轻口味11 小时前
Android应用性能优化
android
全职计算机毕业设计11 小时前
基于 UniApp 平台的学生闲置物品售卖小程序设计与实现
android·uni-app
dgiij12 小时前
AutoX.js向后端传输二进制数据
android·javascript·websocket·node.js·自动化