zoukankan      html  css  js  c++  java
  • 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!  

      

     

      

      

      

     

      

      

  • 相关阅读:
    object c 基础语法
    Object-C 基础知识总结
    【POJ1475】Pushing Boxes-A*(或BFS?)
    【POJ1475】Pushing Boxes-A*(或BFS?)
    【POJ2286】The Rotation Game-迭代加深DFS+可行性剪枝
    【CodeVS1004】四子连棋-迭代加深搜索入门
    【CodeVS1004】四子连棋-迭代加深搜索入门
    【Poj2449】Remmarguts' Date-k短路(A*解法)
    【Poj2449】Remmarguts' Date-k短路(A*解法)
    【HDU4090】Gem and Prince-DFS+可行性剪枝
  • 原文地址:https://www.cnblogs.com/wjtaigwh/p/6047853.html
Copyright © 2011-2022 走看看