Kotlin + Mvp + RxJava + Retrofit 心得体会

Mvp

先上本项目 Github 地址: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 }
}
//基类 P
open 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 的实现类中去实例化,直接使用即可),具体使用请参考代码。

MvpActivity
BasePresenter

解决痛点

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

之前用过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. 有了初步的概念,回头再去看文章会有不一样的体会,会理解作者在说什么,随便学习几个常用的操作符。
  3. 结合自己的理解,最好能从生活中找个例子对照理解。
  4. 学习理解更多的操作符及操作符示意图。
  5. fuck 源码、分享、写文章。

以上方法不适合所有人,以后有机会我也写写对 RxJava 的理解。

Retrofit

Retrofit 是一个遵循 RESTful 设计标准的一个网络请求封装库。

Retrofit 使用了大量的设计模式,其中动态代理 + 注解的思路来声明后端接口非常优雅,再加上提供网络请求适配器及数据转换器的扩展,基本上已满足大部分的业务需求了。

Retrofit简易流程图.jpg

上图是我整理的一个 Retrofit 简易流程图。Retrofit 源码推荐阅读,难度小,里面的技术知识非常多,可以在网上找篇源码分的文章结合着看。

总结

  • 分享自己对 Mvp 的理解。
  • 分享了如何优雅的解决异步调度、进度框显示与隐藏控制、UI 的声明周期绑定问题。
  • 说明项目 Mvp 关系的实现逻辑。
  • 说明项目解决的痛点。
  • 分享 RxJava 的学习方法。
  • 整理出 Retrofit 简易流程图。

有不同意见的可以通过留言或者Issues,项目中重构部分的代码注释比较完善,便于你查阅,如果你喜欢并认可,可以点击喜欢并star项目,谢谢!

本项目 Github 地址:JudyKotlinMvp

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342