Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> RxJava在Android中內存洩漏解決以及RxJava的封裝。

RxJava在Android中內存洩漏解決以及RxJava的封裝。

編輯:關於Android編程

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 lifecycleSubject = BehaviorSubject.create();

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

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

    @NonNull
    @Override
    public  Observable.Transformer 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

沒有加.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  Observable.Transformer io_main(final RxActivity context) {
        return new Observable.Transformer() {

            @Override
            public Observable call(Observable tObservable) {
                return (Observable) 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 extends Subscriber{
    @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

這樣就完成了rxjava的封裝。現在實現了每次訪問網絡的時候顯示對話框,請求完取消對話框,在Activity生命周期Stop的時候取消請求。
關於如何實現了rxJava的封裝,去百度或者Google,搜一下rxJava的操作符compose就能明白了。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved