MiQing Blog

无惧艰难,让生活更幸福更充实,努力起飞!

0%

【Android 开发框架搭建】-网络框架三剑客Okhttp+Rxjava+Retrofit高级篇

前言

上一个文章【Android 开发框架搭建】-网络框架三剑客Okhttp+Rxjava+Retrofit介绍了Android如何搭建轻量级Okhttp+Rxjava+Retrofit网络框架,此篇文章介绍该框架高级功能使用

高级使用

这里介绍框架高级功能使用方式

1.使用RxCache

此组件官方概述: 就像Picasso 缓存您的图片一样,毫不费力缓存您的数据对象。
每个Android Application都是一个客户端应用程序,这意味着仅仅为缓存数据创建数据库并进行维护毫无意义。
事实上,传统方式通过数据库来缓存数据并没有解决根本性的问题:以更加灵活简单的方式配置缓存。
灵感来源于 Retrofit , RxCache是一个用于Android和Java的响应式缓存库,它可将您的缓存需求转换为一个接口进行配置。
当提供一个 observable, single, maybe or flowable (这些是RxJava2支持的响应式数据类型) 这些由耗时操作提供的数据,RxCache确定是否需要subscribe,或覆盖先前缓存的数据。
此决定是基于RxCache的Providers进行配置的。

该组件详细使用方式可参考官方Github文档,此处只会简单结束框架如何使用该组件。
注:使用该组件必须依赖Rxjava库,本框架上篇文章中已经添加过该依赖
Github传送门

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

//添加依赖
//RxCache
api "com.github.VictorAlbertos.RxCache:runtime:1.8.3-2.x"
api "com.github.VictorAlbertos.Jolyglot:gson:0.0.4"

//初始化时开启RxCache setOpenRxCache(true)
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();

new NetworkLoader.Build(this)
//配置项目正式地址及测试地址必须配置
.setBaseUrl("项目正式地址","项目测试地址")
//配置日志打印级别,可不配置默认不打印
.setLogLevel(HttpLoggingInterceptor.Level.HEADERS)
//配置是否开启网络缓存,可不配置默认false不开启
.setOpenCache(true)
//配置是否使用RxCache辅助功能,可不配置默认false不开启
.setOpenRxCache(true)
//自定义token设置,可不配置
.setNetworkHeaderParams(new TokenParams())
//自定义网络异常处理,可不配置
.setResponseErrorListener(new CustomResponseErrorListenerImpl())
.create().build();
}
}

在项目中搭建RxCache相关类
@ProviderKey 定义数据缓存的key
@LifeCache 定义缓存时间策略
其它注解使用请参考官方介绍,上方有传送门

示例1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

//定义RxCacheController类添加RxCache缓存接口,此处返回值必须和Service接口一致,入参参数为网络请求接口返回值,具体注解使用请参考官方介绍
public interface TestRxCacheController {
@ProviderKey("app-net-top")
@LifeCache(duration = 5, timeUnit = TimeUnit.MINUTES) //缓存有效期5分钟
Observable<BaseApiResult<String>> getTop(Observable<BaseApiResult<String>> top);
}


//定义Service接口添加Rxjava返回值类型方法
public interface TestService {

Observable<BaseApiResult<String>> getTop();

}



//定义RxCacheServiceImpl接口实现类,处理RxCache组件创建缓存接口单例对象,
public class TestRxCacheServiceImpl extends BaseRxCacheServiceImpl<TestRxCacheController> implements TestService {

private static TestRxCacheServiceImpl instance = null;

private TestRxCacheServiceImpl() {
super(TestRxCacheController.class);
}

public static TestRxCacheServiceImpl getInstance() {
if (instance == null) {
synchronized (TestRxCacheServiceImpl.class) {
if (instance == null) {
instance = new TestRxCacheServiceImpl();
}
}
}
return instance;
}


//接口实现中获取RxCache接口,传入网络请求方法TestServiceImpl为上篇文章中定义处理网络请求实现类,返回值为Rxjava中Observable类型
@Override
public Observable<BaseApiResult<String>> getTop() {
return getApi().getTop(TestServiceImpl.getInstance().getTop()).compose(RxBus.ApplySchedulers());
}
}



//使用样例
TestRxCacheServiceImpl.getInstance().getTop().subscribe(data -> {
Log.e("MainActivity", "subscribe: "+JSON.toJSONString(data));
}, throwable -> {
Log.e("MainActivity", "onCreate: ", throwable);
});



//此处贴出RxCacheServiceImpl基类,内部处理RxCache创建接口请求。关联NetworkLoader框架单例入口
public class BaseRxCacheServiceImpl<RxCacheController> {

private RxCacheController rxCacheController;

public BaseRxCacheServiceImpl(Class<RxCacheController> clazz) {
try {
rxCacheController = NetworkLoader.getInstance().getRxCache().using(clazz);
}catch (Exception e){
Log.e(NetworkLoader.TAG, "RxCacheError: 配置网络框架时未开启RxCache配置,请检查" );
}
}

protected RxCacheController getApi() {
return rxCacheController;
}

}

2.使用Rxerrorhandler

Rxjava异常错误处理类,定义统一的异常处理接口
Github传送门

示例1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

//添加依赖
//rxerrorhandler
api "me.jessyan:rxerrorhandler:2.1.1"


//初始化时设置setResponseErrorListener(new CustomResponseErrorListenerImpl())
//CustomResponseErrorListenerImpl为自定义的异常处理接口实现类
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();

new NetworkLoader.Build(this)
//配置项目正式地址及测试地址必须配置
.setBaseUrl("项目正式地址","项目测试地址")
//配置日志打印级别,可不配置默认不打印
.setLogLevel(HttpLoggingInterceptor.Level.HEADERS)
//配置是否开启网络缓存,可不配置默认false不开启
.setOpenCache(true)
//配置是否使用RxCache辅助功能,可不配置默认false不开启
.setOpenRxCache(true)
//自定义token设置,可不配置
.setNetworkHeaderParams(new TokenParams())
//自定义网络异常处理,可不配置
.setResponseErrorListener(new CustomResponseErrorListenerImpl())
.create().build();
}
}


//自定义的异常处理接口实现类,这里可继承Base类,内部已经处理基础异常提示,也可自己处理不调用super方法
public class CustomResponseErrorListenerImpl extends BaseResponseErrorListenerImpl {

@Override
public void handleResponseError(Context context, Throwable t) {
super.handleResponseError(context, t);

}
}


//此处贴出框架Base类,以供参考
/**
* 参考MVPArms框架创建的网络异常处理基类
*/
public class BaseResponseErrorListenerImpl implements ResponseErrorListener {

@SuppressLint("ShowToast")
@Override
public void handleResponseError(Context context, Throwable t) {
Log.e(NetworkLoader.TAG, "RxError 捕获", t);
//这里只是对几个常用错误进行简单的处理, 展示这个类的用法, 在实际开发中请您自行对更多错误进行更严谨的处理
String msg = "未知错误";
if (t instanceof UnknownHostException) {
msg = "网络不可用";
} else if (t instanceof SocketTimeoutException) {
msg = "请求网络超时";
} else if (t instanceof HttpException) {
HttpException httpException = (HttpException) t;
msg = convertStatusCode(httpException);
} else if (t instanceof JsonParseException || t instanceof ParseException || t instanceof JSONException || t instanceof JsonIOException) {
msg = "数据解析错误";
}
Toast.makeText(context, msg, Toast.LENGTH_SHORT);
}

private String convertStatusCode(HttpException httpException) {
String msg;
if (httpException.code() == 500) {
msg = "服务器发生错误";
} else if (httpException.code() == 404) {
msg = "请求地址不存在";
} else if (httpException.code() == 403) {
msg = "请求被服务器拒绝";
} else if (httpException.code() == 307) {
msg = "请求被重定向到其他页面";
} else {
msg = httpException.message();
}
return msg;
}

}

//使用样例
TestRxCacheServiceImpl.getInstance().getTop().subscribe(new ErrorHandleSubscriber<BaseApiResult<String>>(NetworkLoader.getInstance().getRxErrorHandler()) {
@Override
public void onNext(@NonNull BaseApiResult<String> longBaseApiResult) {
Log.e("MainActivity", "ErrorHandleSubscriber: "+JSON.toJSONString(longBaseApiResult));
}
});

3.使用Rxpermissions

基于Rxjava编写的Android权限管理库,详细使用参考官方说明

Github传送门

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

//添加依赖
api "com.github.tbruyelle:rxpermissions:0.10.2"

//框架提供简单使用方式
/**
* Rx权限获取工具类
*/
public class RxPermissionsUtil {

/**
* fragment中使用
* 验证权限是否获取成功
* @param fragment 当前页面
* @param permissionsGroup 多个权限数组
* @param booleanConsumer 回调权限是否全部获取
* @return
*/
public static Disposable checkPermissionsHandler(@NonNull Fragment fragment, String[] permissionsGroup, Consumer<Boolean> booleanConsumer) {
RxPermissions rxPermissions = new RxPermissions(fragment);
return rxPermissions.request(permissionsGroup)
.subscribe(booleanConsumer::accept);
}

/**
* activity中使用
* 验证权限是否获取成功
* @param fragmentActivity 当前页面
* @param permissionsGroup 多个权限数组
* @param booleanConsumer 回调权限是否全部获取
* @return
*/
public static Disposable checkPermissionsHandler(@NonNull FragmentActivity fragmentActivity, String[] permissionsGroup, Consumer<Boolean> booleanConsumer) {
RxPermissions rxPermissions = new RxPermissions(fragmentActivity);
return rxPermissions.request(permissionsGroup)
.subscribe(booleanConsumer::accept);
}

/**
* 回收rx资源
* @param disposable 创建的资源
*/
public static void destroyDisposable(Disposable disposable) {
if (disposable != null && !disposable.isDisposed()) {
disposable.dispose();
}
}
}



//使用样例,注意在页面销毁的方法中执行destroyDisposable方法回收执行
RxPermissionsUtil.checkPermissionsHandler(MainActivity.this, new String[]{Manifest.permission.ACCESS_NETWORK_STATE, Manifest.permission.READ_PHONE_STATE}, new Consumer<Boolean>() {
@Override
public void accept(Boolean aBoolean) {
//权限都同意返回true,否者返回false
}
});

总结

该框架现阶段支持的功能都已介绍完毕,希望能够给大家提供帮助。后续会持续更新框架,添加更多适用于该框架的技术。

框架及Demo源码
源码地址 MiQingWang/CommonNetFrame

-------- 本文章已被掏空 学无止境下一章 --------