码迷,mamicode.com
首页 > 移动开发 > 详细

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

时间:2016-05-07 07:04:57      阅读:321      评论:0      收藏:0      [点我收藏+]

标签:

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
RxFragment源码页
Fragment的操作也类似这样。只不过需要继承RxFragment

接下来是封装。

public class RxHelper {
    //子线程运行,主线程回调
    public static <T> Observable.Transformer<T, T> io_main(final RxActivity context) {
        return new Observable.Transformer<T, T>() {

            @Override
            public Observable<T> call(Observable<T> tObservable) {
                return (Observable<T>) tObservable
                        .subscribeOn(Schedulers.io())
                        .doOnSubscribe(new Action0() {
                            @Override
                            public void call() {
                                //每次请求主线程显示对话框
                                ProgressDialogUtil.showProgress(context, "正在加载,请稍候");
                            }
                        })
                        .subscribeOn(AndroidSchedulers.mainThread())
                        .observeOn(AndroidSchedulers.mainThread())
                        .compose(RxLifecycle.bindUntilEvent(context.lifecycle(), ActivityEvent.STOP));
            }
        };
    }

}

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))
                 //只需要加上这一句
                .compose(RxHelper.io_main(SecondActivity.this))
                //这里是new的我们自己的RxSubscriber
                .subscribe(new RxSubscriber<Object>() {
                    @Override
                    public void _onNext(Object o) {
                        L.e("aaaa");
                        tv.setText((String) o);
                    }

                    @Override
                    public void _onError(String msg) {

                    }
                });

这样就完成了rxjava的封装。现在实现了每次访问网络的时候显示对话框,请求完取消对话框,在Activity生命周期Stop的时候取消请求。
关于如何实现了rxJava的封装,去百度或者Google,搜一下rxJava的操作符compose就能明白了。

下班了,来不及解释太多了,如果看的人多,有时间再来更新细节。

项目demo地址(嫌麻烦没有分离模块,直接把项目未搭建完的框架放上来了):
Demo在上传,等会回去更新

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

标签:

原文地址:http://blog.csdn.net/adzcsx2/article/details/51333890

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!