内存泄漏分析
近些年在上学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重新绑定。
文章转发自:Hi大头鬼_深刻浅出RxJava四-在Android中使用响应式编程
个人感觉CSDN上看起来字体不是很爽快,所以转发一下。
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
英文原稿
在第1,2,3篇中,我几乎介绍了RxJava是怎么采纳的。上边我会介绍怎么样在Android中动用RxJava。
RxJava介绍
BehaviorSubject:相当于Observable或许Subscriber,那么些效应是当被订阅后执行onNext执行具体操作后,会优首发送一个暗许值
SubscriptionList:Subscription列表,管理列表中订阅的铲除
Observable.first():仅在率先次订阅中实施
combineLatest():功效于眼下发射的数目项:即使Observable1发射了A并且Observable2发射了B和C,combineLatest()将会分组处理AB和AC
具体RxJava干货请看那里
RxAndroid
RxAndroid是RxJava的一个对准Android平台的增加。它含有了有的可见简化Android开发的工具。
率先,AndroidSchedulers提供了针对性Android的线程系统的调度器。需求在UI线程中运行某些代码?很粗略,只需要采纳AndroidSchedulers.mainThread()
:
retrofitService.getImage(url)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(bitmap -> myImageView.setImageBitmap(bitmap));
一旦你早已创办了温馨的Handler,你可以采用HandlerThreadScheduler
将一个调度器链接到你的handler上。
接着要介绍的就是AndroidObservable,它提供了跟多的意义来协作Android的生命周期。bindActivity()
和bindFragment()
方式暗许使用AndroidSchedulers.mainThread()
来施行观望者代码,那五个方法会在Activity可能Fragment停止的时候文告被观看者为止爆发新的音信。
AndroidObservable.bindActivity(this, retrofitService.getImage(url))
.subscribeOn(Schedulers.io())
.subscribe(bitmap -> myImageView.setImageBitmap(bitmap);
自个儿要好也很欣赏AndroidObservable.fromBroadcast()
主意,它同意你创设一个类似BroadcastReceiver
的Observable
目的。上边的事例突显了什么样在互连网转移的时候被通报到:
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
AndroidObservable.fromBroadcast(context, filter)
.subscribe(intent -> handleConnectivityChange(intent));
最终要介绍的是ViewObservable
,使用它可以给View添加了一些绑定。假若你想在历次点击view的时候都吸纳一个事件,可以运用ViewObservable.clicks()
,可能你想监听TextView的始末变更,可以选取ViewObservable.text()
。
ViewObservable.clicks(mCardNameEditText, false)
.subscribe(view -> handleClick(view));
Awesome-RxJava
RxJava resources
Retrofit
盛名的Retrofit库内置了对RxJava的协助。寻常调用发可以由此选拔一个Callback对象来得到异步的结果:
@GET("/user/{id}/photo")
void getUserPhoto(@Path("id") int id, Callback<Photo> cb);
接纳RxJava,你可以一向重临一个Observable对象。
@GET("/user/{id}/photo")
Observable<Photo> getUserPhoto(@Path("id") int id);
近来您能够轻易动用Observable对象了。你不但可以获取数据,还足以开展转换。
Retrofit对Observable的支撑使得它可以很简单的将多个REST请求结合起来。比如大家有一个伸手是得到照片的,还有一个请求是赢得元数据的,我们就可以将那多少个请求并发的发出,并且等待多少个结实都回到之后再做拍卖:
Observable.zip(
service.getUserPhoto(id),
service.getPhotoMetadata(id),
(photo, metadata) -> createPhotoWithData(photo, metadata))
.subscribe(photoWithData -> showPhoto(photoWithData));
在其次篇里本人显得过一个好像的例子(使用flatMap()
)。那里自个儿只是想浮现以下使用RxJava
Retrofit
可以多多简单地组成多少个REST请求。
Blog
-
给 Android 开发者的 RxJava
详解
–强烈推荐 扔物线的稿子 讲解非常详细 -
NotRxJava懒人专用指南
-那篇入门极力推荐,手把手,深远浅出教你兑现一个简易的RxJava库,更好的驾驭RxJava的已毕思路 -
怎么着进步到RxAndroid1.0
-适合利用Rx 0.x版本的用户升级的时候参考
遗留代码,运行极慢的代码
Retrofit可以回去Observable对象,可是假设你使用的其他库并不支持那样如何做?可能说一个里边的内码,你想把她们转移成Observable的?有如何简单的格局没?
绝大部分时候Observable.just()
和 Observable.from()
可以扶助您从遗留代码中创立 Observable 对象:
private Object oldMethod() { ... }
public Observable<Object> newMethod() {
return Observable.just(oldMethod());
}
地点的例证中一经oldMethod()
足足快是没有何难点的,然则假诺很慢呢?调用oldMethod()
将会阻塞住他所在的线程。
为了缓解那么些难题,可以参见我一贯利用的章程 –
使用defer()
来包装缓慢的代码:
private Object slowBlockingMethod() { ... }
public Observable<Object> newMethod() {
return Observable.defer(() -> Observable.just(slowBlockingMethod()));
}
现在,newMethod()
的调用不会阻塞了,除非你订阅再次来到的observable对象。
开发者前线翻译的一多重很赞的科目
-
那多少个年大家错过的响应式编程
-万分棒的授课响应式编程的篇章。
生命周期
自家把最难的不分留在了最后。怎么样处理Activity的生命周期?首要就是三个难题:
- 在
configuration
改变(比如转屏)之后继续在此以前的Subscription
。
比如您利用Retrofit发出了一个REST请求,接着想在listview中显示结果。就算在互联网请求的时候用户旋转了屏幕如何做?你当然想延续刚才的呼吁,不过怎么搞? - Observable持有Context导致的内存走漏
那几个标题是因为创设subscription
的时候,以某种格局有所了context的引用,尤其是当你和view交互的时候,那太不难发生!如若Observable没有当即竣事,内存占用就会愈来愈大。
噩运的是,没有银弹来解决那七个难题,不过那里有部分引导方案你可以参照。
第四个难题的化解方案哪怕使用RxJava内置的缓存机制,那样你就可以对同一个Observable对象实施unsubscribe/resubscribe
,却毫无再行运行获得Observable的代码。cache()
(或者replay())会继续执行网络请求(甚至你调用了unsubscribe也不会终止)。那就是说你可以在Activity重新成立的时候从cache()的重回值中创立一个新的Observable对象。
Observable<Photo> request = service.getUserPhoto(id).cache();
Subscription sub = request.subscribe(photo -> handleUserPhoto(photo));
// ...When the Activity is being recreated...
sub.unsubscribe();
// ...Once the Activity is recreated...
request.subscribe(photo -> handleUserPhoto(photo));
瞩目,一遍sub是拔取的同一个缓存的伏乞。当然在哪个地方去存储请求的结果恐怕要你自个儿来做,和装有其余的生命周期相关的缓解方案一延虎,必须在生命周期外的某部地点贮存。(retained
fragment可能单例等等)。
其次个难题的化解方案即使在生命周期的某个时刻裁撤订阅。一个很普遍的情势就是应用CompositeSubscription
来持有所有的Subscriptions,然后在onDestroy()
或者onDestroyView()
里打消所有的订阅。
private CompositeSubscription mCompositeSubscription
= new CompositeSubscription();
private void doSomething() {
mCompositeSubscription.add(
AndroidObservable.bindActivity(this, Observable.just("Hello, World!"))
.subscribe(s -> System.out.println(s)));
}
@Override
protected void onDestroy() {
super.onDestroy();
mCompositeSubscription.unsubscribe();
}
您可以在Activity/Fragment的基类里成立一个CompositeSubscription对象,在子类中应用它。
注意! 一旦你调用了
CompositeSubscription.unsubscribe(),那些CompositeSubscription对象就不可用了,
倘若你还想行使CompositeSubscription,就务须在成立一个新的对象了。
四个问题的化解方案都亟待添加额外的代码,要是何人有更好的方案,欢迎告诉本身。
有些科学的牵线操作符的稿子
-
RxMarbles-Interactive
diagrams of Rx Observables
总结
RxJava仍然一个很新的门类,RxAndroid更是。RxAndroid近年来还在外向开发中,也尚未多少好的事例。我打赌一年将来我的一部分提出就会被看做过时了。
一对毋庸置疑的翻译小说
部分规律分析的小说
Test
-
【译】RxJava Essentials
普通话翻译版
-伊凡.Morgillo所写一书的汉语翻译版本 -
【译】RxJava Essentials
汉语翻译版
-伊凡.Morgillo所写一书的中文翻译版本
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
-
learnrxjava
-RxJava例子 -
Intro-To-RxJava
-RxJava实例入门 -
MovieGuide)-An
Android app that showcases the MVP pattern and RxJava -
RxWeather)
-Architecting Android with RxJava -
RxBlur)-用RxJava处理和操作高斯模糊效果的不难用例。
Library
-
rx-preferences
-使SharedPreferences支持RxJava -
RxAndroid
-RxJava的Android拓展 -
RxAndroid
-RxJava的Android拓展 -
RxLifecycle
-扶助使用了RxJava的安卓应用控制生命周期 -
RxBinding
-安卓UI控件的RxJava绑定API -
storio
-协助RxJava的数据库 -
retrofit
-辅助RxJava的互联网请求库 -
sqlbrite
-支持RxJava的sqlite数据库 -
RxPermissions
-RxJava达成的Android运行时权限决定 -
xBus
-简洁的EventBus实现