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!  

  

 

  

  

  

 

  

  

Android--带你一点点封装项目 MVP+BaseActivity+Retrofit+Dagger+RxJava(二)的更多相关文章

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

    1,其实早就想把这些东西给封装封装的,一直没有时间,今天刚好项目进入到测试阶段了,Bug同事在哪儿测试的飞起,但发现提bug的尽然是我(得意脸),然后上午把ios的包测试了一下,顺便把服务器给测挂了( ...

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

    1,这一篇博客是和大家一起来封装我们最后的Dagger2,其实之前也写过关于简单的Dagger2,这里是地址,完全没了解的同学可以先去看一下这篇,感谢很多小伙伴一直在耐心的等待这一篇 2,Dagger ...

  3. Android App的设计架构:MVC,MVP,MVVM与架构经验谈

    相关:http://www.cnblogs.com/wytiger/p/5996876.html 和MVC框架模式一样,Model模型处理数据代码不变在Android的App开发中,很多人经常会头疼于 ...

  4. Android App的设计架构:MVC,MVP,MVVM与架构AAAAA

    1. 架构设计的目的1.1 通过设计使程序模块化,做到模块内部的高聚合和模块之间的低耦合.1.2 这样做的好处是使得程序在开发的过程中,开发人员只需要专注于一点,提高程序开发的效率,并且更容易进行后续 ...

  5. Android -- 带你从源码角度领悟Dagger2入门到放弃(二)

    1,接着我们上一篇继续介绍,在上一篇我们介绍了简单的@Inject和@Component的结合使用,现在我们继续以老师和学生的例子,我们知道学生上课的时候都会有书籍来辅助听课,先来看看我们之前的Stu ...

  6. okhttputils【 Android 一个改善的okHttp封装库】使用(一)

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 本文使用的OKHttp封装库是张鸿洋(鸿神)写的,因为在项目中一直使用这个库,所以对于一些常用的请求方式都验证过,所以特此整理下. ...

  7. okhttputils【 Android 一个改善的okHttp封装库】使用(三)

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 这一篇主要讲一下将OkHttpUtils运用到mvp模式中. 数据请求地址:http://www.wanandroid.com/to ...

  8. Android -- 带你从源码角度领悟Dagger2入门到放弃

    1,以前的博客也写了两篇关于Dagger2,但是感觉自己使用的时候还是云里雾里的,更不谈各位来看博客的同学了,所以今天打算和大家再一次的入坑试试,最后一次了,保证最后一次了. 2,接入项目 在项目的G ...

  9. Android Tools 开发工具库开源项目总结

    在Android开发中,我们不免会遇到使用一些工具库来简化我们的工具代码的编写,以下是本人之前star的开源项目,供大家参考: 一.android_testsuite 项目地址:https://git ...

随机推荐

  1. Spring Autowired 注入失败总是Null

    报错:NullPointerException 分析:错误原因是注入失败? <context:annotation-config/> <context:component-scan ...

  2. strftime 日期时间格式化

    strftime() 函数根据区域设置格式化本地时间/日期,函数的功能将时间格式化,或者说格式化一个时间字符串. size_t strftime(char *strDest,size_t maxsiz ...

  3. oracle 大表 迅速 导出(使用命令行)

    导出: exp dbname/dbpwd@orclname file=c:\xxx.dmp tables=(tablename) 导入:imp ross_delivery/123456@orcl fi ...

  4. Android学习笔记之 android:collapseColumns ,android:shrinkColumns 和stretchColumns

    摘自:http://blog.csdn.net/sjf0115/article/details/7213565/ TableLayout是一个使用复杂的布局,最简单的用法就仅仅是拖拉控件做出个界面,但 ...

  5. 【emWin】例程八:绘制位图

    实验指导书及代码包下载: 链接:http://pan.baidu.com/s/1bpeMYpp 密码:wgtp 实验现象:

  6. java.util.zip获取Zip文件条目InputStream

    package com.test; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import ja ...

  7. sprint2总结

    在sprint第二阶段的学习过程中,前期和后期在学校网络的支持下我们成功的延迟了把代码上传github的时间,在我们自己感觉上看,完成项目的质量比较理想,在经过sprint第一阶段的学习后,部分上的问 ...

  8. Object C中Block用法

    先了解定义C语言的函数指针! int sum (int x, int y) { return x+ y; } // 定义函数 int (*p)(int, int) = sum; NSLog(, )); ...

  9. 完全使用接口方式调用WCF 服务

    客户端调用WCF服务可以通过添加服务引用的方式添加,这种方式使用起来比较简单,适合小项目使用.服务端与服务端的耦合较深,而且添加服务引用的方式生成一大堆臃肿的文件.本例探讨一种使用接口的方式使用WCF ...

  10. Python模拟入栈出栈操作

    目标: 1.编写菜单,提示用户操作选项(push,pop,view,quit) 2.规则:定义列表,先入栈,后出栈,后入栈,先出栈 1.模拟入栈.出栈操作 >>> list1 = [ ...