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. iscrolljs 看API 回顾以前开发中失误

    今天有空 细致的看看iscrolljs api 发现自己以前的几个失误是没看api造成的 失误1 页面a操作 影响了页面b的滚动条 api 解释: options.bindToWrapper The ...

  2. DB2常用命令

    DB2安装启动服务中启动不了,可用command启动并查看windows系统的日志.1.启动数据库  db2start2.停止数据库  db2stop3.连接数据库运行 db2命令之前要先运行db2c ...

  3. JS正则表达式将url转成json格式

    var url = location.search.substr(1); param = {}; console.log(url); url.replace(/([^?&]+)=([^?&am ...

  4. MySQL sql_safe_updates 分析

    我在练习MySQL操作语句时,使用一条完全没有错误的语句: update students set name='drake' where name='chuan'; 却报了如下错误: Error Co ...

  5. MySQL中INFORMATION_SCHEMA是什么?(2)

    information_schema数据库表说明: SCHEMATA:提供了当前mysql实例中所有数据库的信息.是show databases的结果取之此表. TABLES:提供了关于数据库中的表的 ...

  6. HDU 1166 敌兵布阵(分块)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  7. 2016 年 50 个最佳的轻量级 JavaScript 框架和库

    作者:IT程序狮链接:https://zhuanlan.zhihu.com/p/24598210来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 回顾今年已发布的 JS ...

  8. JAVA基础篇NO1--环境变量的配置及命名规则

    标签(空格分隔): java基础 一:计算机概述 计算机:硬件和软件 硬件:控制器 运算器 存储器 输入和输出设备       存储器:外存(硬盘) 内存 软件:系统软件 应用软件   系统软件:wi ...

  9. django对数据查询结果进行排序的方法

    在你的 Django 应用中,你或许希望根据某字段的值对检索结果排序,比如说,按字母顺序. 那么,使用 order_by() 这个方法就可以搞定了. ? 1 2 >>> Publis ...

  10. linux-shell笔记

    1.当从windows拖到shell中无法传递文件时,多半可能没有权限,可用sudo rz来进行手动选择传递 2.连接虚拟机时,ssh 用户名@ip地址,然后会提示输入该虚拟机密码,输入密码即可连接 ...