RxJava+MVP模式下的Nucles框架

内存泄漏分析

最近在学习MVP架构模式中,一直模糊与MVP模式真正能带来什么,我们能从中收获什么。浅显地来说代码分层,易于重构和维护,代码结构分析。但真正在使用过程中,感觉又是可有可无的东西。接下来是我这一天学习查阅资料的体会。

Android项目性能优化中有个必须关注的点是内存泄漏,下面篇幅不在细说内存泄漏工具检测,而在重点说明在实际场景中造成内存泄漏的原因以及解决方案和MVP模式的好处。

  • 内存泄漏常见场景
    1.资源对象没关闭
    比如Cursor游标File文件等,我们在不使用的时候应该关闭它,以便它们的缓冲及时回收内存。面对这一情况一定要养成关闭资源的习惯,因为这种造成泄漏的是长时间大量操作情况下才会复现,会为以后的测试和排查带来困难和风险
    2.构造Adapter适配器时,没有使用缓存的contentView
    3.试着使用Application的Context代替Activity的Context
    Application的Context的生命周期维持整个应用,若在使用过程中持有了该Context,那么在回收过程中因为该Context的生命周期过长,会导致持有对象无法回收
    4.注册没取消
    如广播、服务等,即使程序结束了,但是别的引用程序可能仍然对我们的程序的某个对象的引用,泄漏的内存仍不能被回收。调用广播registerReceiver后记得要调用unregisterReceiver
    5.集合对象没清空
    若在单例中维护集合对象,我们通常把一些对象引用加入到集合中,当我们不需要该对象时,需要把它的引用从集合中移除,避免集合对象占用过多内存
    6.内部类持有外部类导致
    在外部类中定义内部类,如定义一个线程或者Handler,当线程执行耗时操作时关闭Activity,重复该操作,由于线程持有Activity对象,导致Activity对象无法被回收。

线程耗时这种操作是无法避免的,这时就可以使用MVP模式了,把耗时操作放入Presenter中执行,可以定义static静态Presenter,让其不持有Activity对象,这是一种解决思路,但我们可以通过别人对MVP模式的封装来优化内存泄漏的问题。

备注:AsyncTask和RxJava处理异步时,cancle或者unsubscribe仅是不触发onPostExecute或onNext。异步操作还是在跑的,只是没通知回调而已,这个是以前的误区。所以这种内存消耗是无法避免的,我们的优化点就在于避免不必要的异步耗时请求

通常意义上Presenter都有持有View对象,而View经常是Activity和Fragment来扮演,那这不就是矛盾了吗?在Presenter会执行网络请求这些耗时操作,请求结束后会让View作出反馈,那当Activity或者Fragment释放时由于Presenter持有对象那就会Acitivity或者Fragment释放不了可能导致内存泄露的发生。那么怎么解决这个问题呢?可以在View onDestroy销毁时执行Presenter解绑View操作,让View置null,通知GC释放View。当View重新置于前台时让Presenter重新绑定。

Nucles框架

下面会花一定篇幅来介绍MVP封装库Nucles,而Nucles是什么呢,有什么好处?

  • 特性总结
    1.它支持在View/Fragment/Activity的Bundle中保存/恢复Presenter的状态,一个Presenter可以保存它的请求参数到bundles中,以便之后重启它们
    2.它允许一个View实例持有多个Presenter对象
    3.快速实现View和Presenter的绑定
    4.提供线程的基类以便复用
    5.支持在进程重启后,自动重新发起请求,在onDestroy方法中,自动退订RxJava订阅
    6.相当简洁
  • 代码层总结
Paste_Image.png

RequiesPresenter:自定义注解,方便工厂加工Presenter实例
PresenterStorage:Presenter存储单例,方便View重启恢复Presenter
RxPresenter:实现对业务的封装,对业务做解绑操作等
PresenterLifecycleDelegate:Presenter生命周期委托,其中的方法对应View的生命周期。如onSaveInstanceState保存Presenter相关至View的bundlestate,以便onRestoreInstanceState时恢复
NucleusActivity/NucleusFragment/NucleusLayout:持有PresenterLifecycleDelegate对象,统一PresenterLifecycleDelegate管理Presenter生命周期
Delivery相关:涉及RxJava部分,通常是建议Presenter不直接操作View,Delivery实现Observable<数据源>->Observable<View,数据源>转换,动态操作View

通过一张图来作分析:


Paste_Image.png

<View,T>分别对应View对象和数据源。Observable<T>是如通过Retrofit网络请求到的数据源操作。我们需要将数据源操作转换成对View和数据源两者的操作。从中而知我们需要封装个Delivery对象存放View和数据源,然后将网络请求转换成对Delivery。最终subscribe订阅后让Delivery内部处理特定逻辑。那么View对象是从哪里获取到的呢,答案就在构造参数Observable<View> view对象中,这个对象是声明在RxPresenter中的private final BehaviorSubject<View> views = BehaviorSubject.create();

最后附上例子:
https://github.com/hhhhskfk/oschina-mvp

RxJava介绍

BehaviorSubject:相当于Observable或者Subscriber,这个作用是当被订阅后执行onNext执行具体操作后,会优先发送一个默认值
SubscriptionList:Subscription列表,管理列表中订阅的解除
Observable.first():仅在第一次订阅中执行
combineLatest():作用于最近发射的数据项:如果Observable1发射了A并且Observable2发射了B和C,combineLatest()将会分组处理AB和AC

具体RxJava干货请看这里

Awesome-RxJava

RxJava resources

Blog

开发者前线翻译的一系列很赞的教程

一些不错的介绍操作符的文章

一些不错的翻译文章

一些原理分析的文章

Test

App

  • android-gfycat -Android application that loads gifs via gfycat for efficiency's sake

  • JakeWharton/u2020 -Jake大神的项目,里面有RxJava和Retrofit一起使用的例子

  • Avengers - 一个使用Retrofit+RxJava+MVP的app

  • TranslateApp - 一个使用 MVP+Dagger2+RxJava+Retrofit的实现手机端『划词翻译』功能的App - 咕咚翻译

  • AppPlus - 一个可以用于传送Apk文件,提取APK文件等的工具软件。

  • rx-android-architecture -Android中使用Rx的一种架构

  • android-boilerplate -使用RxJava+Retrofit+MVP的app,并了结合详细的测试用例

  • RxJavaApp -用于学习RxJava操作符的APP

Example

Library

Stackoverflow

Video

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

推荐阅读更多精彩内容