Android--带你一点点封装项目 MVP+BaseActivity+Retrofit+Dagger+RxJava(二)

1,昨天我们基本上把MVP给封装起来了,今天接着昨天的东西来结合RxJava把Retrofit把网络框架简单的封装一下,先看一下我们今天实现的效果:

  哈哈 ,还是昨天的效果,好吧 ,我认错。

2,由于这次是把RxJava给接入进来了,所以我们可以对昨天的BasePresenter再次进行封装

  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的绑定和解绑方法在这里实现,并实现订阅功能。

  先看一下我们昨天没有封装的网络请求

 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的封装

由上面的Retrofit我们知道,我们很不确定的是retrofit.create方法,因为有可能我们每次创建的APIService接口是不一样的,所以这里我们可以这样封装一下

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

  然后我们每次并不想每次使用接口都去创建一个Retrofit对象,所以我们可以使用一个单例来解决

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!  

  

 

  

  

  

 

  

  

原文地址:https://www.cnblogs.com/wjtaigwh/p/6047853.html