博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android--带你一点点封装项目 MVP+BaseActivity+Retrofit+Dagger+RxJava(二)
阅读量:5943 次
发布时间:2019-06-19

本文共 17105 字,大约阅读时间需要 57 分钟。

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
implements BasePresenter
{ 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
>() { @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
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 create(Class
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  
void toSubscribe(Observable
o, Subscriber
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 create(Class
service) { return mRetrofit.create(service); } public
void toSubscribe(Observable
o, Subscriber
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
extends Subscriber
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
implements Func1
, T> { @Override public T call(BaseResponse
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
()); Subscription rxSubscription = new ProgressSubscriber<>(new SubscriberOnNextListenter
() { @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!  

  

 

  

  

  

 

  

 

  

转载地址:http://dfwxx.baihongyu.com/

你可能感兴趣的文章
vue相关
查看>>
WebApi跨域的解决方法
查看>>
(转)利用libcurl和国内著名的两个物联网云端通讯的例程, ubuntu和openwrt下调试成功(四)...
查看>>
C#中DataGrid控件的基本使用
查看>>
背景属性的相关属性设置
查看>>
js 获取节点
查看>>
获取app当前可用的剩余内存
查看>>
正则表达式 字符转义
查看>>
分享插件
查看>>
CCF NOI1134 奶牛晒衣服
查看>>
决策树
查看>>
CSS常用属性
查看>>
php正则匹配utf-8编码的中文汉字
查看>>
MemCache在Windows环境下的搭建及启动
查看>>
Python之路(第二十一篇) re模块
查看>>
面向对象进阶
查看>>
第五章 引用类型
查看>>
Spring源码阅读 源码环境搭建(一)
查看>>
修改echarts环形图的牵引线及文字位置
查看>>
<知识库的构建> 5-3 马尔科夫逻辑 Markov logic
查看>>