Pan的简介和设计思路

Pan是一个我在2015年中开始设计并实现的一个安卓端的MV*框架,经过大量的实践和修正,现在的Pan已经十分稳定,成为项目中的核心框架。时至今日,安卓端的MVVM和MVP类型的框架也有一些,但和2015年相比,该有的问题依然存在,而Pan框架的设计思路,也仍然能够超越这些框架,在达到目的的同时,更方便开发者的上手和使用。

臃肿的Activity和Fragment

相信写安卓的人都深有体会,Activity里面一不小心就会有上千行的代码。安卓的MVC设计,Activity本身承担部分Controller的角色;而View的角色由View类型和XML来承担,同时View类型的EventListener由会承担部分的Controller角色;Model交给开发者自由选择。而一旦到真实的实践中,Activity或者Fragment往往会承担大量的代码,主要包含:

  1. 页面的生命周期管理,e.g. onStop
  2. View的渲染细节控制,e.g. 例如setText
  3. 用户交互事件的绑定,e.g. 例如setOnClickListener
  4. 异步网络请求
  5. Fragment生命周期管理

简单的页面或许没什么问题,一旦业务逻辑复杂,Activity到后期基本无法维护,因为要做的事情太多了。

或许你会认为,这是程序员代码能力差导致的。考虑到实际情况,团队中的人也许并不是你能选择的,或者团队成员彼此无法认同对方的编码思路,最终的结果仍然是bad ending。

MVP: 难以上手的mortar,解耦不彻底的nucleusData-binding语法糖

说起MVP框架,首先可能想到的就是square的mortar。mortar很早就写出来了,搭配自家的依赖注入Dagger和Flow。mortar里面很多设计理念很先进,例如通过view组织界面而不是Activity/Fragment,彻底分离View、Presenter、Screen、Activty/Fragment、model层的请求,成功的将整个程序拆成了多种单元,通过依赖注入粘合在一起。这也同样造成了他流行不起来,因为想要mortar,就得把square家族大礼包全部都加进来,彻底的认同一整套square的思维方式,锁定技术栈。学习成本和定制成本都很高。

nucleus是一个轻量级的MVP框架,轻量到……Activity里还是有很多代码,nucleus只把Presenter分离出来,但同时Presenter是与Activity绑定的,这让Presenter的可复用性大大下降,例如一个界面上,局部的Presenter完全可以用到别的Activity/Fragment上的,所以必须要将Presenter和Activity解耦。在实际的编码过程中,ListView或者RecyclerView中Item都是一个可以独立看待的部件,且可能会在其他的非ListView环境中使用。这意味着和Activity绑定后很多内容的复用还得自己想办法。而且nucleus并不管事件跳转,还是写在Activity里,所以Activity还是会臃肿。

官方Data-binding本身只是个setText的语法糖,只把上面提到的View的渲染细节控制解决了一下,而且一定无法彻底解决,逻辑一复杂,还是得用java。

Pan的设计目标

Pan的设计初衷,就是要给Activity瘦身,最好保持在100行以下,甚至50行以下。综合考虑,还有下面这些目标:

  1. 兼容性,可以和不使用Pan框架的代码兼容,支持逐步重构
  2. 解耦Activity和View,界面部件可以在Activity、Fragment、View中复用
  3. View通过ViewModel被动更新,即ViewModel -> View
  4. 分离渲染逻辑和控制逻辑,setText和setOnClickListener不要写在一起
  5. 控制逻辑中,应该能够对当前的Activity、Fragment的生命周期进行监控,从而将UI操作和界面周期控制放在一起
  6. 不追求魔法,低学习成本,KISS

当然,除了上述目标外,到具体实现层面,还有些务实的目标,例如兼容安卓的ViewHolder重用机制。

Pan的模型,MV*

依据上述的目标,Pan的模型比传统的MVC、MVVM模型更加务实,不追求理论上的完美,而在乎实际使用中的易于上手。我们可以称之为MVW(Whatever)

MVC & MVVM & Pan

后续的文章会进一步介绍Pan,并逐渐完善Pan的文档。