android的Live架构
MVC、MVP、MVVM的选择
一开始我们在这几种框架上的选择上就没花太多的心思,因为他们都只是为了实现清晰的分层逻辑,差异化的地方无非是讲UI逻辑、交互逻辑、数据绑定逻辑、业务逻辑堆放在那一层的问题。UI逻辑我们定义为UI控件长什么样,放在那里的逻辑。交互逻辑指的是跟用户互动所需要的逻辑。数据绑定逻辑指数据怎么呈现在界面上的逻辑。业务逻辑指的是因为当前业务不同,跟UI无关的一些程序控制逻辑。
只是看起来很美好的MVC
Live1.0架构上看,MVC的架构能够帮助我们进行良好的分层。Activity(或者Fragment)承担了粘合剂的作用,数据请求后的结果也放在里面。控件的交互交互逻辑虽然收敛在对应的Controller里面了,但是Controller之间的交互逻辑需要放在Fragment中,通过Fragment来调用其他Controller的接口。Live业务是一个典型的业务逻辑简单,UI逻辑、交互逻辑多的场景。各种控件之间的交互很频繁,很快的作为粘合剂的Fragment就不可控地膨胀到2000多行。这时候,添加新的功能或者做修改已有的功能,已经显得很吃力,特别各个组件中因为数据、状态而耦合在一起。在交互复杂的情况下,Activity中因为组件交互的接口越开越多,另外接口也有自己特定的业务名称,除了作者别人改动起来很吃力。这时候,我们又意识到交互逻辑必须要细分为组件自身的交互逻辑,以及组件之间的交互逻辑。
另一方面,粘合剂Fragment中装载的数据是几乎每一个Controller都需要的,往往就在初始化的时候将数据注入进Controller中,来完成数据绑定的逻辑。一不小心,数据绑定的逻辑就从Controller中跑到Fragment了。
开发流程
Live1.0架构中,开发一个组件,需要实现View、Controller、Model,另外Controller还需要在粘合剂Fragment中找到对应的回调实现响应的逻辑,跟其他组件互动的部分需要持有其他组建的View(或Controller).
Live2.0架构
Live2.0架构主要想解决三个问题:
- 每个组件能够独立地变化,状态可以被收敛在组件中。
- 用最少量的、统一的接口来解耦组件间的交互,数据的绑定。
- 交互逻辑、数据请求、业务逻辑、UI逻辑可以复用。
模块化
很自然地,我们就想到可以通过模块化、事件通知机制来解决以上的问题。关键的问题在于如何解决Acitivity中存在大量粘合剂代码。传统的MVC框架只解决了分层的问题,并没有指明模块化的方式。另外我们希望模块化不要造成使用上的难度,接口应该统一、简单易学。玩弄过Google官方出的架构Demo,然而他View、Present的接口也是强业务相关的,并不能实现接口的统一化。
我们最后构想的方案是:既然所有的View在onCreateView的时候都要绑定特定的交互逻辑,onDestroy的时候都要进行销毁,那么每个Controller中实现Fragment的生命周期函数回调就是一件很自然的事情。所以最终的解决方案是Fragment只做生命周期函数的分发,所有的Controller实现Fragment的生命周期回调。
调整后,Fragment彻底变成一个生命周期分发的空壳,每一个View对应一个ViewController,View的绑定交互逻辑、交互逻辑都单独地在Controller中变化.
public class TMVerticalVideoFragment extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mRootView = View.inflate(this.getActivity(), R.layout.fragment_vertical, null);
for (LiveFragmentInterface item :
mViewControllerInterfaceMap.values()) {
item.onCreateView(inflater, container, savedInstanceState);
}
return mRootView;
}
@Override
public void onPause() {
for (LiveFragmentInterface item :
mViewControllerInterfaceMap.values()) {
item.onPause();
}
super.onPause();
}
//省略onViewCreated()、onStop()、onResume()等一大波生命周期函数...
@Override
public void onDestroy() {
super.onDestroy();
for (LiveFragmentInterface item :
mViewControllerInterfaceMap.values()) {
item.onDestroy();
}
}
}
事件分发
之前提到,Live业务的各个组件间的交互逻辑频繁(注意:这里说的不是组件自身的交互逻辑,而是组件与组件间因自身状态变化,而需要控制其他组件同时进行变化的组件间交互。我数了一下一共有26种组件间交互)。显然,这些交互逻辑并不复杂,但是常变。使用事件分发就是最好的选择,接口就不允许常常变化。因此我们实现了简单的事件总线来解耦组件间的交互。
数据绑定
Live业务的数据只依赖少量的Mtop接口,但是这些数据却需要共享给各个组件。我们希望每个组件不要关注数据请求的细节,在数据来的时候,只关注自己需要的数据。另外,Live业务有多个数据源(N个Mtop、配置中心数据、PowerMessage).然而并不是所有的组件都需要关注这么些数据。
解决方案:我们认为数据的请求和处理过程同用户的交互一样,是一种特殊的交互逻辑,数据请求的成功与失败回调也是一种事件通知。数据的绑定固化成特定的接口,对数据感兴趣的Controller只需要实现对应的数据接口,就可以接收到对应的数据。所有Controller中数据绑定的逻辑也固化在特定的数据回调接口中。
/**
* MinSk数据读取Controller
* Created by kaihuan on 16/8/18.
*/
public class MinSkConfigurationController implements LiveFragmentInterface {
public static final String TAG = "live.MinSkConfigurationController";
protected IGetController mFragment;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
JSONObject refreshConfigJson = TMConfigCenterManager.getInstance().getConfigDataObject(getConfigName());
if (refreshConfigJson ==null ){
return;
}
//分发数据
Map<String, LiveFragmentInterface> viewControllerInterfaceMap = mFragment.getViewControllerInterfaceMap();
if (viewControllerInterfaceMap != null) {
for (LiveFragmentInterface item : viewControllerInterfaceMap.values()) {
if (item != null && item instanceof IMinskDataListener) {
((IMinskDataListener) item).onMinskData(getConfigName(),refreshConfigJson);
}
}
}
}
@NonNull
protected String getConfigName() {
return LiveVerticalConstants.MINSK_CONFIG_KEY;
}
// 省略一大波生命周期回到函数..
@Override
public void onFragemntCreated(Fragment fragment) {
this.mFragment = (IGetController) fragment;
}
}
开发流程
Live2.0架构中,开发一个特定的组件就只需要实现自己的View、Controller、Model,在自己的Fragment生命周期回调、数据回调中实现自己的逻辑、改变自己的状态。对组件中需要联动的部分,只需要发送事件通知别人改变。
从切身的体会来说,Live2.0架构简化了开发成本,在View产生的方法,在特定的回到生命周期回调函数中只专心地做自己业务相关的部分,而不需要考虑别人的状态变化。在开发过程中,甚至都见不到别人一丝丝的代码.
双十一我们需要实现三个不同的Live间,由于逻辑的切割足够细,代码方面近乎达到100%的复用。对开发、测试同学来说,工作量至少减少2~3倍。
android的Live架构的更多相关文章
- [转]Android App整体架构设计的思考
1. 架构设计的目的 对程序进行架构设计的原因,归根到底是为了提高生产力.通过设计使程序模块化,做到模块内部的高聚合和模块之间的低耦合.这样做的好处是使得程序在开发的过程中,开发人员只需要专注于一点, ...
- Android入门(二):Android的系统架构
android的系统架构和其操作系统一样,采用了分层的架构.从架构图看,android分为四个层,从高层到低层分别是应用程序层.应用程序框架层.系统运行库层和linux核心层. 从技术方面看,An ...
- Android系统的架构
android的系统架构和其操作系统一样,采用了分层的架构.从架构图看,android分为四个层,从高层到低层分别是应用程序层.应用程序框架层.系统运行库层和linux核心层. 1.应用程序 Andr ...
- fir.im Weekly - iOS/Android 应用程序架构解析
假如问你一个iOS or Android app的架构,你会从哪些方面来说呢? 本期 fir.im Weekly 收集了关于 iOS/Android 开发资源,也加入了一些关于 Web 前端方面的分 ...
- Android 控件架构及View、ViewGroup的测量
附录:示例代码地址 控件在Android开发的过程中是必不可少的,无论是我们在使用系统控件还是自定义的控件.下面我们将讲解一下Android的控件架构,以及如何实现自定义控件. 1.Android控件 ...
- Android 的系统架构
Android 的系统架构 Android其本质就是在标准的Linux系统上增加了Java虚拟机Dalvik,并在Dalvik虚拟机上搭建了一个JAVA的application framework,所 ...
- Android App的架构设计:从VM、MVC、MVP到MVVM
随着Android应用开发规模的扩大,客户端业务逻辑也越来越复杂,已然不是简单的数据展示了.如同后端开发遇到瓶颈时采用的组件拆分思想,客户端也需要进行架构设计,拆分视图和数据,解除模块之间的耦合,提高 ...
- Android系统四层架构分享
Android系统四层架构 个人网站:http://www.51pansou.com Android视频下载:Android视频 Android源码下载:Android源码 如果把Android系统看 ...
- Android的系统架构
转自Android的系统架构 从上图中可以看出,Android系统架构为四层结构,从上层到下层分别是应用程序层.应用程序框架层.系统运行库层以及Linux内核层,分别介绍如下: 1)应用程序层 ...
- 实时Android语音对讲系统架构
本文属于Android局域网内的语音对讲项目系列,<通过UDP广播实现Android局域网Peer Discovering>实现了局域网内的广播及多播通信,本文将重点说明系统架构,音频信号 ...
随机推荐
- bzoj2257: [Jsoi2009]瓶子和燃料
2257: [Jsoi2009]瓶子和燃料 Time Limit: 10 Sec Memory Limit: 128 MB Description jyy就一直想着尽快回地球,可惜他飞船的燃料不够了 ...
- nongsanli
之后的内容只能追加,不可以修改,删除. 1. mysql可以对字段进行MD5加密, 加密插入:INSERT INTO t_user(id,username,PASSWORD) VALUES('5 ...
- 01_Linux安装
一.VMware创建一个虚拟机 下一步 .下一步 .下一步 ..前方高能 二.安装CentOS 6.7 next -> 选择 中文简体 -> 美式键盘,直接下一步 ,一直下一 ...
- 17年年终总结——走过2017,迎来2018Flag
引言 记得大概从大学毕业到现在都没有写作啥总结性的文章了(ps:应该是没写过啥长篇大论了),所以也不知道怎么个起头.我也闲聊的方式起头吧. 其实跨入18年就想着写篇总结,总结下自己17年的得与失,不足 ...
- 文件锁FileLock
1.文件锁的定义 FileLock是文件锁,进程锁,用于进程间并发,控制不同程序(JVM)对同一文件的并发访问. FileLock是java 1.4 版本后出现的一个类,它可以通过对一个可写文件(w) ...
- BZOJ 3309: DZY Loves Math [莫比乌斯反演 线性筛]
题意:\(f(n)\)为n的质因子分解中的最大幂指数,求\(\sum_{i=1}^n \sum_{j=1}^m f(gcd(i,j))\) 套路推♂倒 \[ \sum_{D=1}^n \sum_{d| ...
- POJ Ikki's Story IV - Panda's Trick [2-SAT]
题意: 圆上n个点,m对点之间连边,连在园内或园外,所有边不相交是否可行 发现两对点连线都在内相交则都在外也相交,那么只有一个在内一个在外啦,转化为$2-SAT$问题 #include <ios ...
- js中的this和箭头函数中的this
一.ES6 允许使用"箭头"(=>)定义函数. // var f = v => v;// 上面的箭头函数等同于: // var f = function(v) {// ...
- 解决xshell评估期已过的问题
问题:时间长没有打开xshell,今天突然打开提示评估期已过,如下图所示: 点击采购会弹出购买的界面,(对于我们这些程序屌怎么会花899购买一款软件)点击取消就会退出. 解决方法: 卸载这个要收费的版 ...
- 张高兴的 Windows 10 IoT 开发笔记:部署 ASP.NET Core 2 应用
今天是大年初二,都去走亲戚了吧,享受一下这难得的能和亲友相聚的时光.而我就不一样了,今天一回到家就又开始瞎折腾了,哈哈哈. 问题背景 最近花了点时间用 ASP.NET Core 2 写了个个人博客,中 ...