RxJava在Android中内存泄漏解决以及RxJava的封装

本文转自:http://blog.csdn.net/adzcsx2

RxJava在现在是一个非常前卫的异步框架,也是由于他非常新,所以比较难以驾驭。

像okhttp直接在onStop或者onDestroy 调用它的cancel方法就行了,但是Rxjava并没有那么简单。

因为假如每次请求都得到Observable对象,然后再onStop中unsubscribe取消,这样很不利于封装。而且会造成代码量很多,所以我找到了用rxlifecycle的解决方案。

先导包

    compile ‘com.trello:rxlifecycle:0.5.0‘
    compile ‘com.trello:rxlifecycle-components:0.5.0‘

然后写RxActivity,原作者github上有源码,我根据自己的情况稍微修改了一下。

import android.os.Bundle;
import android.support.annotation.CallSuper;
import android.support.annotation.NonNull;
import android.support.v4.app.FragmentActivity;

import com.trello.rxlifecycle.ActivityEvent;
import com.trello.rxlifecycle.ActivityLifecycleProvider;
import com.trello.rxlifecycle.RxLifecycle;

import rx.Observable;
import rx.subjects.BehaviorSubject;

/**
 * Created by a on 2016/5/6.
 */
public class RxActivity extends FragmentActivity implements ActivityLifecycleProvider {

    public final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();

    @NonNull
    @Override
    public Observable<ActivityEvent> lifecycle() {
        return lifecycleSubject.asObservable();
    }

    @NonNull
    @Override
    public <T> Observable.Transformer<T, T> bindUntilEvent(@NonNull ActivityEvent event) {
        return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
    }

    @NonNull
    @Override
    public <T> Observable.Transformer<T, T> bindToLifecycle() {
        return RxLifecycle.bindActivity(lifecycleSubject);
    }

    @Override
    @CallSuper
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        lifecycleSubject.onNext(ActivityEvent.CREATE);
    }

    @Override
    @CallSuper
    protected void onStart() {
        super.onStart();
        lifecycleSubject.onNext(ActivityEvent.START);
    }

    @Override
    @CallSuper
    protected void onResume() {
        super.onResume();
        lifecycleSubject.onNext(ActivityEvent.RESUME);
    }

    @Override
    @CallSuper
    protected void onPause() {
        lifecycleSubject.onNext(ActivityEvent.PAUSE);
        super.onPause();
    }

    @Override
    @CallSuper
    protected void onStop() {
        lifecycleSubject.onNext(ActivityEvent.STOP);
        super.onStop();
    }

    @Override
    @CallSuper
    protected void onDestroy() {
        lifecycleSubject.onNext(ActivityEvent.DESTROY);
        super.onDestroy();
    }
}

用自己的activity继承RxActivity。在网络请求的地方加上

.compose(RxLifecycle.bindUntilEvent(lifecycle(), ActivityEvent.STOP))

意思是在Stop周期的时候取消请求。

我用了上一篇博客上传图片的例子,现在是MainActivity进入SecondActivity之后,点击按钮之后上传一张图片,然后获得返回结果。

File file = new File(Environment.getExternalStorageDirectory() + "/123.png");
        HttpUtil.getIImagePP().upLoadImage("c1a2b3ab56a2f218aed9b2ab3c16ce88", "be8318b73cef1c2bcafb6c8a77922436", HttpUtil.postFileParams("img", file))
                //封装了在子线程中运行,主线程subscribe,下文会讲如何封装。
                .compose(RxHelper.io_main(SecondActivity.this))
                //.compose(RxLifecycle.bindUntilEvent(lifecycle(), ActivityEvent.STOP))
                .subscribe(new RxSubscriber<Object>() {
                    @Override
                    public void _onNext(Object o) {
                        L.e("aaaa");
                        tv.setText((String) o);
                    }

                    @Override
                    public void _onError(String msg) {

                    }
                });

没有加.compose(RxLifecycle.bindUntilEvent(lifecycle(), ActivityEvent.STOP))这一句,点按钮上传,然后马上返回上一个activity的Log日志:

返回到MainActivity之后大概2秒钟之后,出现了这句

05-06 18:37:58.590 15642-15642/com.sanniuben.myapplication E/way: aaaa

加了之后就没有返回了。

可见他在onStop的时候取消了这次请求。

RxLifecycle Github :https://github.com/trello/RxLifecycle

RxFragment源码页

https://github.com/trello/RxLifecycle/tree/master/rxlifecycle-components/src/main/java/com/trello/rxlifecycle/components

Fragment的操作也类似这样。只不过需要继承RxFragment

接下来是封装。

public class RxHelper<T> {
    //子线程运行,主线程回调
    //注意这里不能设置成静态,设置成静态之后泛型就不能用了。这也是我之前为什么subcribe的泛型只能为Object的原因,现在博客已经更新。
    public Observable.Transformer<T, T> io_main(final RxActivity context) {
        return new Observable.Transformer<T, T>() {

            @Override
            public Observable<T> call(Observable<T> tObservable) {

                Observable<T> tObservable1 = (Observable<T>) tObservable
                        .subscribeOn(Schedulers.io())
                        .doOnSubscribe(new Action0() {
                            @Override
                            public void call() {
                                //ProgressDialogUtil.showProgress中实现了弱引用,不会造成内存泄漏。
                                ProgressDialogUtil.showProgress(context, "正在加载,请稍候");
                            }
                        })
                        .subscribeOn(AndroidSchedulers.mainThread())
                        .observeOn(AndroidSchedulers.mainThread())
                        .compose(RxLifecycle.bindUntilEvent(context.lifecycle(), ActivityEvent.STOP));

                return tObservable1;

            }
        };
    }
}

Subscriber

/**
 * Created by a on 2016/5/6.
 */
public abstract class RxSubscriber<T> extends Subscriber<T>{
    @Override
    public void onCompleted() {
        //完成的时候取消对话框
        ProgressDialogUtil.dismiss();
    }

    @Override
    public void onError(Throwable e) {
        e.printStackTrace();

        _onError(e.getMessage());
        if (!NetUtils.isConnected(MyApplication.getContextObject())) {
            Toast.makeText(MyApplication.getContextObject(), "请求失败,请检查网络!", Toast.LENGTH_SHORT).show();
            ProgressDialogUtil.dismiss();;
            return;
        }
    }

    @Override
    public void onNext(T t) {
        _onNext(t);
    }

    public abstract void _onNext(T t);

    public abstract void _onError(String msg);
}

现在来看一下,新的请求

File file = new File(Environment.getExternalStorageDirectory() + "/123.png");
        HttpUtil.getIImagePP().upLoadImage("c1a2b3ab56a2f218aed9b2ab3c16ce88", "be8318b73cef1c2bcafb6c8a77922436", HttpUtil.postFileParams("img", file))
                 //只需要加上这一句,RxHelper<T>泛型内容需要自己输入
                .compose(new RxHelper<String>.io_main(SecondActivity.this))
                //这里是new的我们自己的RxSubscriber
                .subscribe(new RxSubscriber<String>() {
                    @Override
                    public void _onNext(String o) {
                        L.e("aaaa");
                        tv.setText(o);
                    }

                    @Override
                    public void _onError(String msg) {

                    }
                });

这样就完成了rxjava的封装。现在实现了每次访问网络的时候显示对话框,请求完取消对话框,在Activity生命周期Stop的时候取消请求。

Transformer实际上就是一个Func1< Observable< T >, Observable< R>>,换言之就是:可以通过它将一种类型的Observable转换成另一种类型的Observable,和调用一系列的内联操作符是一模一样的。

compose和flatMap()的区别:

What About flatMap()?

1、At this point, you may be wondering what the difference is between using compose() and flatMap(). They both emit Observable, which means both can reuse a series of operators, right?

The difference is that compose() is a higher level abstraction: it operates on the entire stream, not individually emitted items. In more specific terms:

2、compose() is the only way to get the original Observable from the stream. Therefore, operators that affect the whole stream (like subscribeOn() and observeOn()) need to use compose().

In contrast, if you put subscribeOn()/observeOn() in flatMap(), it would only affect the Observable you create in flatMap() but not the rest of the stream.

3、compose() executes immediately when you create the Observable stream, as if you had written the operators inline. flatMap() executes when its onNext() is called, each time it is called. In other words, flatMap() transforms each item, whereas compose() transforms the whole stream.

flatMap() is necessarily less efficient because it has to create a new Observable every time onNext() is called. compose() operates on the stream as it is.

If you want to replace some operators with reusable code, use compose(). flatMap() has many uses but this is not one of them.

引用自:http://blog.danlew.net/2015/03/02/dont-break-the-chain/

简单的说就是:

1、compose是影响整条流,而flatMap仅仅是影响它自己转化的部分。

2、flatMap转后的是在调用next()后执行,而compose是直接执行。。

3、flatMap在next()后执行都会创建一个Observable 对象(以供下一次操作做处理形成链式结构),而compose更像是拼接到流上面去,一次性执行完,所以相对来说compose的效率更高一点。

本文代码:http://download.csdn.net/detail/jdsjlzx/9529124

时间: 2024-11-07 10:12:38

RxJava在Android中内存泄漏解决以及RxJava的封装的相关文章

RxJava在Android中内存泄漏解决以及RxJava的封装。

RxJava在现在是一个非常前卫的异步框架,也是由于他非常新,所以比较难以驾驭. 像okhttp直接在onStop或者onDestroy 调用它的cancel方法就行了,但是Rxjava并没有那么简单. 因为假如每次请求都得到Observable对象,然后再onStop中unsubscribe取消,这样很不利于封装.而且会造成代码量很多,所以我找到了用rxlifecycle的解决方案. 先导包 compile 'com.trello:rxlifecycle:0.5.0' compile 'com

linux中内存泄漏的检测(二)定制化的malloc/free

<linux中内存泄漏的检测(一)最简单的方法>介绍了最简单的内存泄漏检测方法,这种方法虽然简单,却有很多现实的问题,导致它不能用于实际的生产中. 直接使用这种方法肯定是不现实的,因为: (1)把整个工程里所有调用malloc/free的地方都改成my_malloc/my_free,代码改动很大. (2)通常动态库和静态库的代码是没有权限修改的. 今天就来解决这个问题,动态地决定让程序使用自己的还是系统的内存管理接口. wrap选项 不希望修改产品代码,那么用于申请/释放内存的接口还是mall

Android防止内存泄漏以及MAT的使用

Android发生内存泄漏最普遍的一种情况就是长期保持对Context,特别是Activity的引用,使得Activity无法被销毁.这也就意味着Activity中所有的成员变量也没办法销毁.本文仅介绍如何避免这种情况的发生,其他如Bitmap没有及时回收导致的OOM异常暂不讨论. 一.防止内存泄漏 什么情况下会长时间保持对某个Activity的引用呢?主要有以下两种情况: 1.某个static变量保持对Activity的引用 2.线程保持Activity的引用 由于静态变量是长驻内存的,甚至在

linux中内存泄漏的检测(四)记录泄漏的大小

<linux中内存泄漏的检测(三)定制化的new/delete>讲到,利用C++的函数重载的特性,使C++的代码,也能方便地为new/delete加上用于检测内存泄漏的统计代码.然而,也因此引入的新的问题. 目前的统计方式仅仅统计申请/释放内存的次数,并没有统计每次申请/释放内存的大小. 这种方法对于C来说是够用了,因为在C中申请和释放的大小是相同的,而在C++中就不一定了. 考虑以下两种情况: (1)申请了子类的空间却只释放了父类的空间 father *pF = new son; delet

[转]Android中内存占用的含义:(VSS,PSS,RSS,USS)

Android中内存占用的含义:(VSS,PSS,RSS,USS) 作者: andforce 分类: 安卓系统 发布时间: 2013-09-07 00:03 ?1,915 浏览数 6没有评论 在eng版本的android手机上,可以执行:procrank 会列出来VSS,PSS,RSS,USS的占用信息. VSS:Virtual Set Size:how virtual memory associated witth process.([共享]进程所占的虚拟内存是多少,跟物理内存没有多大关心.)

Android开发常见的Activity中内存泄漏及解决办法

上一篇文章楼主提到由Context引发的内存泄漏,在这一篇文章里,我们来谈谈Android开发中常见的Activity内存泄漏及解决办法.本文将会以"为什么""怎么解决"的方式来介绍这几种内存泄漏. 在开篇之前,先来了解一下什么是内存泄漏. 什么是内存泄漏? 内存泄漏是当程序不再使用到的内存时,释放内存失败而产生了无用的内存消耗.内存泄漏并不是指物理上的内存消失,这里的内存泄漏是值由程序分配的内存但是由于程序逻辑错误而导致程序失去了对该内存的控制,使得内存浪费. 怎

Android 常见内存泄漏的解决方式

在Android程序开发中.当一个对象已经不须要再使用了,本该被回收时.而另外一个正在使用的对象持有它的引用从而导致它不能被回收.这就导致本该被回收的对象不能被回收而停留在堆内存中,内存泄漏就产生了. 内存泄漏有什么影响呢? 它是造成应用程序OOM的主要原因之中的一个.由于Android系统为每一个应用程序分配的内存有限.当一个应用中产生的内存泄漏比較多时.就难免会导致应用所须要的内存超过这个系统分配的内存限额,这就造成了内存溢出而导致应用Crash. 一.单例造成的内存泄漏 Android的单

Webview内存泄漏解决办法2

在这次开发过程中,需要用到webview展示一些界面,但是加载的页面如果有很多图片就会发现内存占用暴涨,并且在退出该界面后,即使在包含该webview的Activity的destroy()方法中,使用webview.destroy();webview=null;对内存占回收用还是没有任何效果.有人说,一旦在你的xml布局中引用了webview甚至没有使用过,都会阻碍重新进入Application之后对内存的gc.包括使用MapView有时一会引发OOM,几经周折在网上看到各种解决办法,在这里跟大

Android中内存泄露与如何有效避免OOM总结

一.关于OOM与内存泄露的概念 我们在Android开发过程中经常会遇到OOM的错误,这是因为我们在APP中没有考虑dalvik虚拟机内存消耗的问题. 1.什么是OOM OOM:即OutOfMemoery,顾名思义就是指内存溢出了.内存溢出是指APP向系统申请超过最大阀值的内存请求,系统不会再分配多余的空间,就会造成OOM error.在我们Android平台下,多数情况是出现在图片不当处理加载的时候. Android系统为每个应用程序分配的内存有限,当一个应用中产生的内存泄漏比较多时,就难免会