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!
Android--带你一点点封装项目 MVP+BaseActivity+Retrofit+Dagger+RxJava(二)的更多相关文章
- Android--带你一点点封装项目 MVP+BaseActivity+Retrofit+Dagger+RxJava(一)
1,其实早就想把这些东西给封装封装的,一直没有时间,今天刚好项目进入到测试阶段了,Bug同事在哪儿测试的飞起,但发现提bug的尽然是我(得意脸),然后上午把ios的包测试了一下,顺便把服务器给测挂了( ...
- Android--带你一点点封装项目 MVP+BaseActivity+Retrofit+Dagger+RxJava(三)
1,这一篇博客是和大家一起来封装我们最后的Dagger2,其实之前也写过关于简单的Dagger2,这里是地址,完全没了解的同学可以先去看一下这篇,感谢很多小伙伴一直在耐心的等待这一篇 2,Dagger ...
- Android App的设计架构:MVC,MVP,MVVM与架构经验谈
相关:http://www.cnblogs.com/wytiger/p/5996876.html 和MVC框架模式一样,Model模型处理数据代码不变在Android的App开发中,很多人经常会头疼于 ...
- Android App的设计架构:MVC,MVP,MVVM与架构AAAAA
1. 架构设计的目的1.1 通过设计使程序模块化,做到模块内部的高聚合和模块之间的低耦合.1.2 这样做的好处是使得程序在开发的过程中,开发人员只需要专注于一点,提高程序开发的效率,并且更容易进行后续 ...
- Android -- 带你从源码角度领悟Dagger2入门到放弃(二)
1,接着我们上一篇继续介绍,在上一篇我们介绍了简单的@Inject和@Component的结合使用,现在我们继续以老师和学生的例子,我们知道学生上课的时候都会有书籍来辅助听课,先来看看我们之前的Stu ...
- okhttputils【 Android 一个改善的okHttp封装库】使用(一)
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 本文使用的OKHttp封装库是张鸿洋(鸿神)写的,因为在项目中一直使用这个库,所以对于一些常用的请求方式都验证过,所以特此整理下. ...
- okhttputils【 Android 一个改善的okHttp封装库】使用(三)
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 这一篇主要讲一下将OkHttpUtils运用到mvp模式中. 数据请求地址:http://www.wanandroid.com/to ...
- Android -- 带你从源码角度领悟Dagger2入门到放弃
1,以前的博客也写了两篇关于Dagger2,但是感觉自己使用的时候还是云里雾里的,更不谈各位来看博客的同学了,所以今天打算和大家再一次的入坑试试,最后一次了,保证最后一次了. 2,接入项目 在项目的G ...
- Android Tools 开发工具库开源项目总结
在Android开发中,我们不免会遇到使用一些工具库来简化我们的工具代码的编写,以下是本人之前star的开源项目,供大家参考: 一.android_testsuite 项目地址:https://git ...
随机推荐
- Leetcode Unique Paths II
Follow up for "Unique Paths": Now consider if some obstacles are added to the grids. How m ...
- Leetcode Longest Common Prefix
Write a function to find the longest common prefix string amongst an array of strings. class Solutio ...
- EntityFrame CodeFirst 自动生成表
来源:http://msdn.microsoft.com/zh-cn/data/jj193542 本视频和分步演练介绍通过 Code First 开发建立新数据库.这个方案包括建立不存在的数据库(Co ...
- Win下常用命令大全
定时关机命令win+R输入 Shutdown -s //后面不加时间参数,默认的是倒计时30秒后关机Shutdown -s -t 0 //立刻关机shutdown -s -t 100 //100s后关 ...
- c++聪聪看书(满分代码)
聪聪是一个善良可爱.睿智聪慧的好孩子.聪聪喜欢看书,这一天她在看一本书时看到了这样一个问题:给你一个正整数n,你要将它分成若干个自然数Ai的和的形式,并且使得这若干个自然数Ai的乘积尽量大,并输出最大 ...
- Jvascript简介
一.Javascript就是我们所说的脚本语言.它不同于C++/java等语言,它更加灵活! 正因为其灵活性,没有那么多的规章制度,也是我们容易学的地方,但很多时候也是 令人无奈的地方! 二.我们要知 ...
- Python脚本配合Linux计划任务工作
经常遇到直接运行Python脚本没有问题,但是一放入/etc/crontab之后就歇菜的情况,总结了一下,大致需要注意以下几点: 1. 脚本首行加入#!/usr/bin/env python 2. 脚 ...
- 好看的IDE配色方案让代码看起来不再那么凶猛了
写这篇小文的初衷是,笔者是原教旨主义者,一直坚持用IDE默认的配色方案.另外也觉得网上黑色系的配色方案太过bling bling了.但今天尝试用新的配色方案后,兴奋地发现对代码的好感度大幅提升. 嗯, ...
- equals(),hashcode(),克隆学习心得
equals(),hashcode(),克隆学习心得 其实在开发时候,很少去重写equals(),hashCode()方法,但是有些时候业务需要还是要重写. 注意: 重写equals()方法一定要重写 ...
- oracle分组取第一条
SELECT * FROM (SELECT ROW_NUMBER() OVER(PARTITION BY x ORDER BY y DESC) rn,test1.* FROM test1) WHERE ...