QQ群:AndroidMVP 555343041
更新日志:
2017/1/31:AOP新增SysPermissionAspect支持动态申请系统权限切片,轻松适配6.0+
2017/1/27:AOP新增DbRealmAspect支持Realm数据库,数据库突破你想像的简单(年夜特供)
2017/1/8: 使用Apt封装Retrofit生成ApiFactory替换掉所有的Repository,狂删代码
2017/1/7: 使用DataBinding替换掉所有的ButterKnife,狂删代码
2017/1/6: 使用DataBinding替换掉所有的ViewHolder,狂删代码,从此迈向新时代
2016/12/30:新增TRouter全局路由,使用apt生成代码实现页面跳转
2016/12/29:去掉BaseMultiVH新增VHClassSelector支持更完美的多ViewHolder
2016/12/28:使用Apt生成全局的ApiFactory替代所有的Model
2016/12/27:增加了BaseMultiVH扩展支持多类型的ViewHolder
2016/12/26:抽离CoreAdapterPresenter优化TRecyclerView
安卓AOP实战:面向切片编程
Android实用技巧之:用好泛型,少写代码
安卓AOP实战:APT打造极简路由
全局路由TRouter,更优雅的页面跳转
安卓AOP实战:Javassist强撸EventBus
加入OkBus,实现注解传递事件
安卓AOP三剑客:APT,AspectJ,Javassist
1、去掉所有反射>2、新增apt初始化工厂,替换掉了dagger2。>3、新增aop切片,处理缓存和日志
关键词 MVP+Retrofit+Rxjava+MaterialDesign+LeanCloud+NodeJS
简书:http://www.jianshu.com/p/b49958e1889d
weibo:http://weibo.com/1917320262
Github:https://github.com/north2016/T-MVP
QQ群:AndroidMVP 555343041
导语
删繁就简三秋树,领异标新二月花
传统MVP给人的第一感觉通常是接口和类的暴涨,将Activity中除V之外的繁杂操作搬到P之后依然臃肿不堪。MVP从来都不是救命稻草,只能锦上添花,不能雪中送炭。也许在权衡利弊之后,很多人会对MVP望而却步。 现在 我们换一个思路,取其精华,去其糟粕,完成T-MVP大变身。
一、T-MVP简介
话不多说,先上图:
T-MVP架构图
下面,看看如何利用泛型把我们从繁杂重复的劳动中解救出来。
后台接口用的是LeanCloud的REST API,数据通过Node爬虫从网页上获取,先爬出十个页面的列表,然后每一个列表爬进去获取文章详情。爬虫代码见app.js。(建议替换成自己申请的appId和appKey)。
1、页面分层结构
宗旨:纯粹界面操作交互,不需要MP参与的行为,尽量V自己做,保证MVP职责清晰,P只有干净简洁的协助VM的业务逻辑操作,M只处理数据操作。
登录契约类相比谷歌官方Contract类,多了一个Model,用于将P中繁杂的数据操作分离解耦,让P层变得简洁明了,只处理M和V相关操作即可,登录Present的全部代码:
登录Present的全部代码RxManage用于管理订阅者、观察者、以及事件。(详见代码)
例如:
发送事件: mRxManage.post(C.EVENT_LOGIN, user);
接收事件:mRxManage.on(C.EVENT_LOGIN, arg ->mView.initUserInfo((_User) arg));
LoginModel的全部代码:
LoginModel的全部代码
抽离出Model不仅各层更加分工明确便于Model的复用,而且大大简化了Presenter的代码量,让P层更简洁更专注。职能清爽,一目了然。
2、列表页
例如一个列表页,用户关心的,只有列表的Item展示:
mTRecyclerView.setItemView(ItemView.class);
不需要在当前页面写网络请求,不需要写下拉刷新和分页加载更多的回调,不需要写任何Adapter,只需要这一句即可。因为用泛型在TRecyclerView里面写过抽象层的操作,将监听和数据的获取封装成通用模板,从此可以一劳永逸了。
比如,分页加载的封装操作:
TRecyclerView部分代码
对于有HeaderView的List也一样:
mTRecyclerView.setHeaderView(HeaderView.class).setItemView(ItemView.class);
ViewHolder也是相当简洁的写法:
ViewHolder
至此,项目可以永远告别OnRefresh ,onLoadMore ,Adapter。
3、项目结构
利用泛型封装的一些Base类,总代码不超过1000行,也是T-MVP的核心:
![T-MVP项目结构])X{FRT]K9SMSZ}CY.jpg](http:https://img.haomeiwen.com/i751860/281b2b0198b49042.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
T-MVP利用泛型解藕和高度抽象封装之后,相较于传统MVC和MVP代码量大大精简,架构的代码量也是精简至极:
例如BasePresenter的全部代码:
BasePresenter的全部代码二、T-MVP的目标
//TODO
- 1 整理Base类,吸纳意见之后,继续优化封装,将简洁进行到底。让MVP不再背负繁杂的名声。
- 2 发布到github
- 3 争取发布到jcenter
正在做:
-
1 添加持久层数据存储realm
-
2 recyclerview支持多种LayoutManager (GridLayoutManager StaggeredGridLayoutManager),支持多头部,多列表类型,多底部。
-
3 添加fragment的MVP,同时也解决了一个页面需要多个P的问题
-
4 尽量把反射去掉,免得有人抓住把柄说性能不好
-
5 把框架部分隔离出来,单独做成Library
-
6 用apt自动帮我们生成一些黑科技代码,达到事半功倍的效果
三、进度
- 1登录、注册
- 2列表分类
- 3文章详情 文章评论列表
- 4用户中心 用户评论列表
- 5更换头像
- 6用户列表
项目截图:
7247fc46jw1f3p5r5tsynj20u01hcwl0.jpg 7247fc46jw1f3p5r8cjjhj20u01hc47t.jpg 7247fc46jw1f3p5r35jqnj20u01hcdt4.jpg 7247fc46jw1f3p5rceufqj20u01hcnaz.jpg
网友评论
在TRecyclerView的item中处理点击事件应该怎样处理。
或者说我有一个需求是点击item中的某个view,去请网络应该怎样去处理??
在线等。。。
别潜水,,快粗来!!!!!!!
> Unable to delete file: D:\T-MVP-master\app\build\intermediates\exploded-aar\com.android.databinding\adapters\1.2.1\jars\classes.jar
请问这个问题怎么解决?把 app文件夹下的build文件夹删除也不行
{
"code": 401,
"error": "Unauthorized."
}
是什么原因啊?
不过有几个问题
1、数据持久层,应该在model层来处理,可是博主这样设计数据持久化怎么办?
2、p与m层的创建是在v层创建的,就是说v持有了m、p的引用,这样的耦合可否给个合理的解释?
我举个例子. 打开 activity ,加载500条数据, 这时候View调用调用P层.loadData ,P层 loadData 方法里面调用RxMannge.add(Model.getDataFromNetWork) 就是把model的这个方法作为一个observable 放进了RxManage ,这个时候,用户迫不及待的关闭了activity ,但是网络请求还在继续,但是在activity ondestory 的时候,调用了 P 层的clear 方法,把observable 取消注册了,过了5秒之后, 网络请求成功,这时候model把结果给 P层, P层拿到这个observable , 不会做任何操作,因为这个observable 已经被unsubcribe了. 然后 activity 被GC,Model 被GC,P层被GC ,这样就避免了内存泄漏.因为我们model 层 始终是以observable 来返回的
OnEvent(Observable<?> mObservable, Action1<Object> mAction1) {
第一个参数 就是rxbus中,register注册事件源返回的Observable吗?
大家可以参考下下面项目dagger2+mvp的框架,希望支持下
https://github.com/CarlLu/MVPframe
public interface IView{
void startSomeActivity(); //错,Presenter不能控制View,只能设置数据
void showTextView(); //错,Presenter不能控制View,只能设置数据
void setActivityPrepareData(DownloadInfo info);//对
void setViewAdapterData(List<Data> listData);//对
void showToast(int resId);//错 ResourceId不是从Model层中获取,View选取哪个ResourceId来显示是View自己的责任
}