Android--帶你一點點封裝項目 MVP+BaseActivity+Retrofit+Dagger+RxJava(二)

1,昨天咱們基本上把MVP給封裝起來了,今天接着昨天的東西來結合RxJava把Retrofit把網絡框架簡單的封裝一下,先看一下咱們今天實現的效果:java

  哈哈 ,仍是昨天的效果,好吧 ,我認錯。android

2,因爲此次是把RxJava給接入進來了,因此咱們能夠對昨天的BasePresenter再次進行封裝api

  BaseRxPresenter.java緩存

package com.qianmo.myview2.base;

import rx.Subscription;
import rx.subscriptions.CompositeSubscription;

/**
 * Created by wangjitao on 2016/11/9 0009.
 * 基於Rx的Presenter的訂閱者的生命週期
 */
public class BaseRxPresenter<T extends BaseView> implements BasePresenter<T> {

    protected T mView;
    protected CompositeSubscription mCompositeSubscription;

    protected void addSubscrebe(Subscription subscription) {
        if (mCompositeSubscription == null) {
            mCompositeSubscription = new CompositeSubscription();
        }
        mCompositeSubscription.add(subscription);
    }

    protected void unSubscribe() {
        if (mCompositeSubscription != null) {
            mCompositeSubscription.unsubscribe();
        }
    }

    @Override
    public void attachView(T view) {
        this.mView = view;
    }

    @Override
    public void detachView() {
        this.mView = null;
        unSubscribe();
    }
}

  將View的綁定和解綁方法在這裏實現,並實現訂閱功能。網絡

  先看一下咱們昨天沒有封裝的網絡請求app

 Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Constant.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        AppVersionService movieService = retrofit.create(AppVersionService.class);

        movieService.getVersion()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<BaseResponse<VersionBean>>() {
                    @Override
                    public void onStart() {
                        mView.showProgressDialog();
                    }

                    @Override
                    public void onCompleted() {
                        mView.DissProgressDialog();
                    }

                    @Override
                    public void onError(Throwable e) {
                        mView.DissProgressDialog();
                        mView.ShowToast("請求出錯");
                    }

                    @Override
                    public void onNext(BaseResponse<VersionBean> versionBeanBaseResponse) {
                        if (Integer.valueOf(currentVersion.replace(".", "")) < Integer.valueOf(versionBeanBaseResponse.getData().getCode().replace(".", ""))) {
                            // mView.showUpdateDialog(versionBean);
                            //這裏表示發現新版本
                            mView.ShowToast("發現最新版本");
                        } else {
                            //表示這就是最新版本
                            mView.ShowToast("已是最新版本");
                        }
                    }
                });

  由於這只是咱們的一個接口,若是是多個呢?  咱們每一次都要new一個Retrofit對象嗎? 而且每次要請求網絡的時候都要重寫Subscriber的這四個onstart()、onCompleted()、onError()、onNext(),通常咱們的Activity只關心最後的數據問題即它只想要咱們Presenter最後返回給它Bean的數據進行出來就行,其它一切東西它並非很想去只掉,好的,咱們就能夠幫它來解決這些問題框架

3,Retrofit的封裝ide

由上面的Retrofit咱們知道,咱們很不肯定的是retrofit.create方法,由於有可能咱們每次建立的APIService接口是不同的,因此這裏咱們能夠這樣封裝一下ui

public <T> T create(Class<T> service) {
        return mRetrofit.create(service);
    }

  而後咱們每次並不想每次使用接口都去建立一個Retrofit對象,因此咱們可使用一個單例來解決this

private static RetrofitManager sInstace;

    /**
     * 私有構造方法
     */
    private RetrofitManager() {

        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        if (BuildConfig.DEBUG) {
            // https://drakeet.me/retrofit-2-0-okhttp-3-0-config
            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
            builder.addInterceptor(loggingInterceptor);
        }
        File cacheFile = new File(Constant.PATH_CACHE);
        Cache cache = new Cache(cacheFile, 1024 * 1024 * 50);
        Interceptor cacheInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                if (!SystemUtil.isNetworkConnected()) {
                    request = request.newBuilder()
                            .cacheControl(CacheControl.FORCE_CACHE)
                            .build();
                }
                Response response = chain.proceed(request);
                if (SystemUtil.isNetworkConnected()) {
                    int maxAge = 0;
                    // 有網絡時, 不緩存, 最大保存時長爲0
                    response.newBuilder()
                            .header("Cache-Control", "public, max-age=" + maxAge)
                            .removeHeader("Pragma")
                            .build();
                } else {
                    // 無網絡時,設置超時爲4周
                    int maxStale = 60 * 60 * 24 * 28;
                    response.newBuilder()
                            .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                            .removeHeader("Pragma")
                            .build();
                }
                return response;
            }
        };
        //設置緩存
        builder.addNetworkInterceptor(cacheInterceptor);
        builder.addInterceptor(cacheInterceptor);
        builder.cache(cache);
        //設置超時
        builder.connectTimeout(10, TimeUnit.SECONDS);
        builder.readTimeout(20, TimeUnit.SECONDS);
        builder.writeTimeout(20, TimeUnit.SECONDS);
        //錯誤重連
        builder.retryOnConnectionFailure(true);
        mOkHttpClient = builder.build();

        mRetrofit = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .baseUrl(Constant.BASE_URL)
                .client(mOkHttpClient)
                .build();
    }

    /**
     * 建立單例
     */
    public static RetrofitManager getInstace() {
        if (sInstace == null) {
            synchronized (RetrofitManager.class) {
                sInstace = new RetrofitManager();
            }
        }
        return sInstace;
    }

  能夠看到,再建立的時候咱們進行了一系列OkHttpClient和Retrofit的初始化,而後在上面的沒封裝的代碼中咱們每一都要寫

 movieService.getVersion()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())

  之類的代碼,因此咱們在提供一個方法在封裝一下

 public  <T> void toSubscribe(Observable<T> o, Subscriber<T> s) {
        o.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(s);
    }

  ok,這樣咱們的RetrofitManager差很少就封裝完畢了,再看看完整的代碼

  RetrofitManager.java

package com.qianmo.myview2.network;

import android.content.Context;
import android.provider.SyncStateContract;

import com.qianmo.myview2.BuildConfig;
import com.qianmo.myview2.api.ZhiHuApi;
import com.qianmo.myview2.model.bean.DailyListBean;
import com.qianmo.myview2.model.bean.ThemeListBean;
import com.qianmo.myview2.utils.Constant;
import com.qianmo.myview2.utils.SystemUtil;

import java.io.File;
import java.io.IOException;
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

/**
 * Created by wangjitao on 2016/11/9 0009.
 * retrofit管理類
 */
public class RetrofitManager {

    private static final int DEFAULT_TIMEOUT = 5;

    private Retrofit mRetrofit;
    private OkHttpClient mOkHttpClient;
    private static RetrofitManager sInstace;

    /**
     * 私有構造方法
     */
    private RetrofitManager() {

        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        if (BuildConfig.DEBUG) {
            // https://drakeet.me/retrofit-2-0-okhttp-3-0-config
            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
            builder.addInterceptor(loggingInterceptor);
        }
        File cacheFile = new File(Constant.PATH_CACHE);
        Cache cache = new Cache(cacheFile, 1024 * 1024 * 50);
        Interceptor cacheInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                if (!SystemUtil.isNetworkConnected()) {
                    request = request.newBuilder()
                            .cacheControl(CacheControl.FORCE_CACHE)
                            .build();
                }
                Response response = chain.proceed(request);
                if (SystemUtil.isNetworkConnected()) {
                    int maxAge = 0;
                    // 有網絡時, 不緩存, 最大保存時長爲0
                    response.newBuilder()
                            .header("Cache-Control", "public, max-age=" + maxAge)
                            .removeHeader("Pragma")
                            .build();
                } else {
                    // 無網絡時,設置超時爲4周
                    int maxStale = 60 * 60 * 24 * 28;
                    response.newBuilder()
                            .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                            .removeHeader("Pragma")
                            .build();
                }
                return response;
            }
        };
        //設置緩存
        builder.addNetworkInterceptor(cacheInterceptor);
        builder.addInterceptor(cacheInterceptor);
        builder.cache(cache);
        //設置超時
        builder.connectTimeout(10, TimeUnit.SECONDS);
        builder.readTimeout(20, TimeUnit.SECONDS);
        builder.writeTimeout(20, TimeUnit.SECONDS);
        //錯誤重連
        builder.retryOnConnectionFailure(true);
        mOkHttpClient = builder.build();

        mRetrofit = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .baseUrl(Constant.BASE_URL)
                .client(mOkHttpClient)
                .build();
    }

    /**
     * 建立單例
     */
    public static RetrofitManager getInstace() {
        if (sInstace == null) {
            synchronized (RetrofitManager.class) {
                sInstace = new RetrofitManager();
            }
        }
        return sInstace;
    }

    public Retrofit getRetrofit() {
        return mRetrofit;
    }


    public <T> T create(Class<T> service) {
        return mRetrofit.create(service);
    }





    public  <T> void toSubscribe(Observable<T> o, Subscriber<T> s) {
        o.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(s);
    }
}

  把Retrofit的建立給解決了咱們再看時解決每次重寫Subscriber的這四個onstart()、onCompleted()、onError()、onNext()的問題,因爲這一塊我以前的博客寫過的,就不給你們廢話了,只是大體的說一下思路了,建立一個ProgressSubscriber.java讓它繼承自Subscriber,並添加網絡請求時所須要的加載框,在onStart()方法中顯示加載框,在onCompleted()、onError()影藏加載框,再經過接口回調將onNext()中產生的數據回調給presenter中去通知UI更新就行,直接上代碼了

  ProgressSubscriber.java

package com.qianmo.myview2.network;

import android.content.Context;
import android.widget.Toast;

import java.net.ConnectException;
import java.net.SocketTimeoutException;

import rx.Subscriber;

/**
 * Created by wangjitao on 2016/11/3 0003.
 */
public class ProgressSubscriber<T> extends Subscriber<T> implements ProgressCancelListener {

    private SubscriberOnNextListenter mSubscriberOnNextListenter;
    private ProgressDialogHandler mProgressDialogHandler;
    private Context context;

    public ProgressSubscriber(SubscriberOnNextListenter mSubscriberOnNextListenter, Context context) {
        this.mSubscriberOnNextListenter = mSubscriberOnNextListenter;
        this.context = context;
        mProgressDialogHandler = new ProgressDialogHandler(context, this, true);
    }

    /**
     * 在開始訂閱的時候顯示加載框
     */
    @Override
    public void onStart() {
        if (mProgressDialogHandler != null) {
            mProgressDialogHandler.obtainMessage(ProgressDialogHandler.SHOW_PROGRESS_DIALOG).sendToTarget();
        }
    }

    /**
     * 在完成的時候進行隱藏
     */
    @Override
    public void onCompleted() {
        Toast.makeText(context, "Get Top Movie Completed", Toast.LENGTH_SHORT).show();
        dismissProgressDialog();
    }

    /**
     * 在出錯的時候也進行影藏
     *
     * @param e
     */
    @Override
    public void onError(Throwable e) {
        if (e instanceof SocketTimeoutException) {
            Toast.makeText(context, "網絡中斷,請檢查您的網絡狀態", Toast.LENGTH_SHORT).show();
        } else if (e instanceof ConnectException) {
            Toast.makeText(context, "網絡中斷,請檢查您的網絡狀態", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(context, "error:" + e.getMessage(), Toast.LENGTH_SHORT).show();
        }
        dismissProgressDialog();
    }

    @Override
    public void onNext(T t) {
        mSubscriberOnNextListenter.next(t);
    }

    @Override
    public void onCancelProgress() {
        if (!this.isUnsubscribed()) {
            this.unsubscribe();
        }
    }

    private void showProgressDialog() {
        if (mProgressDialogHandler != null) {
            mProgressDialogHandler.obtainMessage(ProgressDialogHandler.SHOW_PROGRESS_DIALOG).sendToTarget();
        }
    }

    private void dismissProgressDialog() {
        if (mProgressDialogHandler != null) {
            mProgressDialogHandler.obtainMessage(ProgressDialogHandler.DISMISS_PROGRESS_DIALOG).sendToTarget();
            mProgressDialogHandler = null;
        }
    }
}

  ProgressDialogHandler.java

package com.qianmo.myview2.network;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Handler;
import android.os.Message;

/**
 * Created by liukun on 16/3/10.
 */
public class ProgressDialogHandler extends Handler {

    public static final int SHOW_PROGRESS_DIALOG = 1;
    public static final int DISMISS_PROGRESS_DIALOG = 2;

    private ProgressDialog pd;

    private Context context;
    private boolean cancelable;
    private ProgressCancelListener mProgressCancelListener;

    public ProgressDialogHandler(Context context, ProgressCancelListener mProgressCancelListener,
                                 boolean cancelable) {
        super();
        this.context = context;
        this.mProgressCancelListener = mProgressCancelListener;
        this.cancelable = cancelable;
    }

    private void initProgressDialog(){
        if (pd == null) {
            pd = new ProgressDialog(context);

            pd.setCancelable(cancelable);

            if (cancelable) {
                pd.setOnCancelListener(new DialogInterface.OnCancelListener() {
                    @Override
                    public void onCancel(DialogInterface dialogInterface) {
                        mProgressCancelListener.onCancelProgress();
                    }
                });
            }

            if (!pd.isShowing()) {
                pd.show();
            }
        }
    }

    private void dismissProgressDialog(){
        if (pd != null) {
            pd.dismiss();
            pd = null;
        }
    }

    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case SHOW_PROGRESS_DIALOG:
                initProgressDialog();
                break;
            case DISMISS_PROGRESS_DIALOG:
                dismissProgressDialog();
                break;
        }
    }

}

 因爲咱們每次請求的時候有可能會出現一些請求的錯誤,,因此咱們這裏建立一個HttpResultFunc.java,來判斷此次請求是否成功

package com.qianmo.myview2.network;

import com.qianmo.myview2.response.BaseResponse;

import rx.functions.Func1;

/**
 * Created by Administrator on 2016/11/9 0009.
 */
public class HttpResultFunc<T> implements Func1<BaseResponse<T>, T> {

    @Override
    public T call(BaseResponse<T> httpResult) {
        if (httpResult.getCode() != 200) {
            throw new ApiException(httpResult.getCode());
        }
        return httpResult.getData();
    }
}

  這樣基本上咱們的東西就封裝的差很少了,再看一下咱們的CheckVersion中調用代碼

Observable observable = RetrofitManager.getInstace()
                .create(AppVersionService.class).getVersion()
                .map(new HttpResultFunc<VersionBean>());
        Subscription rxSubscription = new ProgressSubscriber<>(new SubscriberOnNextListenter<VersionBean>() {
            @Override
            public void next(VersionBean versionBean) {
                mView.setUpdateText(versionBean.getDes());
            }
        }, context);
        RetrofitManager.getInstace().toSubscribe(observable, (Subscriber) rxSubscription);
        addSubscrebe(rxSubscription);

  已經比較簡潔了(自我安慰中,小菜鳥畢竟技術有限),ok這樣網絡就大體的封裝好了,下一篇將Dagger加進來就差很少了

  See You Next Time!  

相關文章
相關標籤/搜索