专栏名称: code小生
公众号:「code小生」,乐于分享的码农
目录
相关文章推荐
开发者全社区  ·  Top2本硕:一把好牌打的稀烂 ·  5 小时前  
开发者全社区  ·  86岁范大师北大携35岁新夫人公开露面 ·  昨天  
开发者全社区  ·  星星眼小笼包女星离婚的内幕 ·  2 天前  
开发者全社区  ·  中高端岗位也不保?deepseek干掉了量化研究员 ·  2 天前  
开发者全社区  ·  真High! ·  3 天前  
51好读  ›  专栏  ›  code小生

Kotlin + Mvp + RxJava + Retrofit 心得体会

code小生  · 掘金  · android  · 2019-04-12 02:21

正文

code小生,一个专注 Android 领域的技术平台

公众号回复 Android 加入我的安卓技术群

作者:Walkud链接:https://www.jianshu.com/p/4cb1a56acf9e声明:本文已获 Walkud 授权发表,转发等请联系原作者授权

先上本项目 Github 地址:https://github.com/Walkud/JudyKotlinMvp

首先声明

本项目是参考 git-xuhao/KotlinMvp ,对原项目 Mvp 核心代码及 Adapter 代码按照自己的想法进行了重构,布局 (xml) 文件(除 fragment_mine.xml )、工具类、自定义 View 都直接使用的原项目的文件,本项目的主要目的是为了 Kotlin 学习,将自己对 Java 版 Mvp 的理解用 Kotlin 实现。

说明

我希望用尽可能少的文字和代码来说明是自己对 Mvp 的理解。

Mvp

Mvp 最主要的目的就是为了解耦,让各个模块各司其职。

M (Model) 负责业务模型的构建,可简单理解为P所需要的数据结构就在这一层处理及封装(包括网络、Sqlite、sp等)。

可参考 MainModel ,Model的粒度根据实际情况自行控制。

P (Presenter) 负责处理业务逻辑,可简单理解为业务中的UI操作、 if 判断等。

UI操作不仅仅是调用 UI 的数据更新操作,还包含何时显示进度框、隐藏进度框、绑定Ui生命周期等。

model.getSearchResult(keyWords!!)        .compose(NetTransformer())//异步调度(异步发起请求 --> 主线程回调)        .compose(ProgressTransformer(view))//进度框的显示与隐藏        .compose(bindUntilOnDestroyEvent())//绑定UI生命周期 (PS: 生命周期时机可控)        .subscribe(object : RxSubscribe<HomeBean.Issue>() {            ……        })

以上代码用三行代码进行了异步调度、进度框显示与隐藏控制、UI 的声明周期绑定(防止内存泄漏)操作,这就是 RxJava 魅力所在。

可参考 VideoDetailPresenter

V (View) 负责提供 UI 交互的能力,可简单理解为 V 监听到用户的点击事件 --> P 处理业务逻辑 --> V 更新UI。

Activity、Fragment 为 V ,其中 Adapter、View(xml、自定义View)、Dialog 等为 V 的一部分,所有的交互事件都放在 Activity 和 Fragment 中进行监听,便于日后定位。

项目中 Mvp 实现

//依赖关系View  < —— > Presenter —— > Model

本项目中使用泛型来指定依赖关系,且直接依赖的具体实现,并没有依赖抽象,可以有效提高开发效率,但违背了设计原则,个人认为过于看重这些原则,导致开发效率降低也有些得不偿失。

//基类 V  (MvpFragment 同理)abstract class MvpActivity<P> : MvcActivity() {    val presenter: P by lazy {        getP()    }    /**     * 获取逻辑处理实例,子类实现     */    abstract fun getP(): P    …… }//具体实现class SearchActivity : MvpActivity<SearchPresenter>() {//泛型指定 P 的依赖关系    // 这里实例化 P 并且 注入 V    override fun getP() = SearchPresenter().apply { view = this@SearchActivity }}//基类 Popen class BasePresenter<V : Any, out M> : ViewLifecycle() {    /**     * UI视图,即Activity或Fragment     */    var view: V by Delegates.notNull()    /**     * 业务模型,即XXXModel,这里使用java反射(kotlin反射太慢,暂时不建议使用)创建示例,省去在每个Presenter中创建实例     */    val model: M by lazy {      //这里使用 Java 反射实例化 M,      ReflectionUtils.getSuperClassGenricType<M>(this, 1)    }    ……}//具体实现class SearchPresenter : BasePresenter<SearchActivity, MainModel>() {//泛型指定 V 和 M 的具体实现    ……}

通过上面代码,Mvp 之间的关系就建立起来了,需要注意的是 M 是通过Java 反射实例化的(省去在 P 的实现类中去实例化,直接使用即可),具体使用请参考代码。

MvpActivityBasePresenter

解决痛点

抽象(创建过多无用的接口)

之前用过 Mvp 的在这点上应该深有体会,直接依赖具体实现可以很好的解决这个问题,对于需要复用的地方也可以指定泛型为接口,从而达到可复用目的,实际项目中这种复用需求很少。

异步导致的内存泄漏

异步时间过长而界面已退出,回调中依然隐式的持有 Activity 实例,这个问题在开发中很常见,所以本项目中使用了 RxJava (异步利器)来处理异步问题,由于它的灵活性,在加上另外一位大神开源库 RxLifecycle 可以很方便的处理这个问题,而且使代码也非常美观(一行代码搞定),最重要的是处理时机可控(比如在 onStop 或 onDestory )。

//为了控制篇幅,偷懒了,参照前面贴的代码compose(bindUntilOnDestroyEvent())//绑定UI生命周期 (PS: 生命周期时机可控)

进度UI的控制

对于弹框进度、下拉刷新、上拉加载、异常布局等控制问题,使用 RxJava 可以完美的解决,一行代码解放开发者大脑,不需要再去想何时显示、何时隐藏。

//为了控制篇幅,偷懒了,参照前面贴的代码compose(ProgressTransformer(view))//进度框的显示与隐藏

ProgressTransformer

交互都由 Activity 或 Fragment 来处理

有没有同学遇到修改遗留 Bug 找某个点击事件的时候,要跳转 N 个类,最后发现事件监听里面发了一个 Event 事件,然后又得找是谁消费了事件,发现居然有 N 个类都有消费(一脸懵逼,我的真实遭遇。。。) ,本项目的处理方式是将最终的监听都放在 V 中 的 addListener 方法中,找交互事件的时候可以快速定位。

RxJava

RxJava 使代码更连贯、逻辑更清晰(特别是去看原来的代码)、简洁,项目中使用了 RxJava 优雅的解决了异步调度、进度框显示与隐藏控制、UI 的声明周期绑定的问题,使用简单灵活。

RxJava 对于初学者来说,算是一个比较难上手的库,网上也有很多文章,但看完之后也不知道哪里好用,哪里简洁。在这里分享一个我最初学习的方法:

  1. 先依葫芦画瓢,硬着头皮去使用,对 RxJava 有个初步的概念。

  2. 有了初步的概念,回头再去看文章会有不一样的体会,会理解作者在说什么,随便学习几个常用的操作符。







请到「今天看啥」查看全文


推荐文章
开发者全社区  ·  Top2本硕:一把好牌打的稀烂
5 小时前
开发者全社区  ·  86岁范大师北大携35岁新夫人公开露面
昨天
开发者全社区  ·  星星眼小笼包女星离婚的内幕
2 天前
开发者全社区  ·  真High!
3 天前
北京吃货小分队  ·  串串自助,吃300串还能免单
7 年前
黄生看经济  ·  拐点已至:从工业化到城市化
7 年前