前言: 本人也是一個小菜鳥,寫這篇文章意在拋磚引玉,希望有的大神可以來看看我哪里有不足之處,幫我答疑解難!假如有剛接觸的小伙伴,也可以一起進步......項目已經(jīng)上傳到github上面了,下載地址有興趣的可以來下載,歡迎issues
首先,看本博客之前你需要掌握以下技能:
1.你是一個Android開發(fā)工程師,且迫切希望改變自己項目里面的moudle層
2.你對java的解耦思想有一定了解,基礎(chǔ)相對較扎實
3.你要對Android的okHttp3有一定的了解,比如攔截器等...
4.對Retrofit有一定的了解,最起碼自己寫過Demo測試過
5.對java1.8的RetroLamada知道是什么
6.對RxJava有一定的了解,以及1.x升級到2.x做了什么改動
7.對google的Gson熟練掌握
8.對以上我所說的你確定你都達到了,當(dāng)然沒達到也沒關(guān)系,后面我會一點一點的講
首先先貼上一個maven倉庫的地址,方便你查詢當(dāng)前maven倉庫里面各種庫的最新版本.
然后是RxJava 的github地址俗話說得好,任何不懂的問題都可以通過查詢源碼來解決,人家的注釋給你寫的很明白,英文水平?jīng)Q定了你的高度.
然后是Retrofit的github地址,個人一直比較喜歡Retrofit這個網(wǎng)絡(luò)加載框架,Retrofit的英文翻譯是改進,更新, 花樣翻新...我覺得他們起名字的時候更傾向的是第三種翻譯吧,哈哈...
還有okHttp的github地址,okHttp在HttpClient安卓棄用了以后(當(dāng)然也不能講棄用,是沒法用),是Android開發(fā)中的一個利器,簡潔方便,但是就是使用原生的話有點費勁,搭配Retrofit以后可以說是如虎添翼.
好了啰啰嗦嗦的說了這么多廢話,下面進入正題!
首先是我的項目結(jié)構(gòu)圖
寫這個大致分為以下幾步,先列出來后面會一步一步的講:
- 1 依賴倒入
- 2 封裝BaseActivity和App(其實這一步每個人有每個人的想法,我只是建議這樣寫,不足之處望指出)
- 3 net包下兩個攔截器以及自定義Observer
- 4 bean包下HttpResult類(針對自己的接口編寫)
- 5 api包下面的四個類
大致分為上面的幾個步驟,不要著急,容我倒杯茶慢慢道來...
1. 依賴導(dǎo)入
//okhttp
compile 'com.squareup.okhttp3:okhttp:3.7.0'
compile 'com.squareup.okio:okio:1.12.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.7.0'
//gson
compile 'com.google.code.gson:gson:2.8.0'
//retrofit2
compile 'com.squareup.retrofit2:retrofit:2.2.0'
compile 'com.squareup.retrofit2:converter-gson:2.2.0'
compile 'com.squareup.retrofit2:converter-scalars:2.2.0'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'
//rxJava
compile'io.reactivex.rxjava2:rxjava:2.0.1'
compile'io.reactivex.rxjava2:rxandroid:2.0.1'
下面我依次介紹一下上面幾個依賴的具體用處
okhttp注釋下面的三個
前兩個不用多說,用過okhttp的自然都知道,需要注意的一點是第一個版本不能低于3.4.1,具體原因我也不是很清楚,有知道原因的煩請告訴我一聲.第三個顧名思義,是okhttp自己提供的log攔截器,方便我們在控制臺輸出okhttp信息
Retrofit2注釋下面的四個
第一個是不必多說,第二個作用是讓Retrofit支持gson,添加這個以后可以直接結(jié)果出來就生成我們想要的JavaBean.第三個, <strong>A Converter which supports converting strings and both primitives and their boxed types to text/plain bodies.</strong>源碼里面是這么介紹的,意思自己理解,我就不關(guān)公門前耍大刀了,畢竟自己是四級425分的渣渣...最后一個是Retrofit適配RxJava2必須要添加的
RxJava注釋下面的兩個
第一個是RxJava 第二個是RxJava適配Android的
注:gson注釋下面的就不用我廢話了吧
2. 封裝BaseActivity和App
因為我在項目里面多次用到Application的Context,以及我的工具類里面需要用到Context的地方也都是用的Application的,所以簡單寫了一下就是下面這個樣子的
public class App extends Application{
public static Application INSTANCE;
@Override
public void onCreate() {
super.onCreate();
INSTANCE = this;
T.register(this);
NetUtils.register(this);
}
}
下面貼上我的T這個類,這個類主要是做一些Toast的工作
/**
* Toast統(tǒng)一管理類
*/
public class T {
public static Context mContext;
private static Toast toast;
private T() {
/* cannot be instantiated */
throw new UnsupportedOperationException("cannot be instantiated");
}
public static void register(Context context) {
mContext = context;
}
/**
* 短時間顯示Toast
*/
public static void showShort(CharSequence message) {
if (mContext==null){
throw new RuntimeException("unRegister Context in Application");
}
if (toast != null) {
toast.cancel();
}
toast = Toast.makeText(mContext, message, Toast.LENGTH_LONG);
toast.setText(message);
toast.show();
}
public static void showShort(int resId) {
if (mContext==null){
throw new RuntimeException("unRegister Context in Application");
}
if (toast != null) {
toast.cancel();
}
toast = Toast.makeText(mContext, mContext.getString(resId), Toast.LENGTH_LONG);
toast.setText(mContext.getString(resId));
toast.show();
}
}
友情提示:自定義App以后不要忘了在Manifest.xml的application節(jié)點下面加入android:name=".App"
這一句!
接下來是我自己的BaseActivity
/**
* Created by ziabo on 2017/5/9.
* Activity的Base類
*/
public abstract class BaseActivity extends AppCompatActivity{
private CompositeDisposable mCompositeDisposable;
private ApiService mApiService;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (mApiService == null){
mApiService = ApiService.getApiService();
}
setContentView(initContentView());
initUIAndListener();
initData();
}
/**
* 設(shè)置layout
*/
protected abstract int initContentView();
/**
* 初始化UI和Listener
*/
protected abstract void initUIAndListener();
/**
* 初始化數(shù)據(jù)
*/
protected abstract void initData();
/**
* 管理所有建立的鏈接,在onDestroy中清空 mCompositeDisposable
*/
protected void addDisposable(Disposable disposable){
if (mCompositeDisposable==null){
mCompositeDisposable = new CompositeDisposable();
}
mCompositeDisposable.add(disposable);
}
@Override
protected void onDestroy() {
if (mCompositeDisposable != null){
mCompositeDisposable.clear();
}
super.onDestroy();
}
}
里面有些看不懂的地方不要著急,可以先就看我那三個protected abstract的方法就好,這三個是強制要子類實現(xiàn)的,我們的Activity寫出來的時候就是下面這個樣子,比較簡潔明了..
public class TestActivity extends BaseActivity{
@Override
public int initContentView() {
return 0;//此處放上你的Layout的id
}
@Override
protected void initUIAndListener() {
}
@Override
protected void initData() {
}
}
注: 一定要注意方法的先后執(zhí)行順序!
3. net包下兩個攔截器以及自定義Observer
說到攔截器,這個就不得不提一下okHttp的強大之處,此處的兩個攔截器一個攔截器是發(fā)送請求的時候的調(diào)用的,另一個是結(jié)果以jsonString返回回來的時候調(diào)用的,他們分別的用處我會在下面細講!先上代碼
RequestInterceptor
/**
* 類名稱:請求前攔截器,這個攔截器會在okhttp請求之前攔截并做處理
*/
public class RequestInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
//請求定制:添加請求頭
Request.Builder requestBuilder = original
.newBuilder()
.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
//設(shè)置cookie
// String cookie= App.getCookie();
// if (StringUtil.checkStr(cookie)) { //cookie判空檢查
// requestBuilder.addHeader("Cookie", cookie);
// }
//如果是post的情況下,請求體定制:統(tǒng)一添加參數(shù),此處演示的是get請求,因此不做處理
if (original.body() instanceof FormBody) {
FormBody.Builder newFormBody = new FormBody.Builder();
FormBody oidFormBody = (FormBody) original.body();
for (int i = 0; i < oidFormBody.size(); i++) {
newFormBody.addEncoded(oidFormBody.encodedName(i), oidFormBody.encodedValue(i));
}
//當(dāng)post請求的情況下在此處追加統(tǒng)一參數(shù)
// String client = Constants.CONFIG_CLIENT;
//
// newFormBody.add("client", client);
requestBuilder.method(original.method(), newFormBody.build());
}
return chain.proceed(requestBuilder.build());
}
}
里面的注釋寫的個人覺得挺全的,有什么問題可以具體詳細再問!
ResponseInterceptor
/**
* 結(jié)果攔截器,這個類的執(zhí)行時間是返回結(jié)果返回的時候,返回一個json的String,對里面一些特殊字符做處理
* 主要用來處理一些后臺上會出現(xiàn)的bug,比如下面聲明的這三種情況下統(tǒng)一替換為:null
*/
public class ResponseInterceptor implements Interceptor {
private String emptyString = ":\"\"";
private String emptyObject = ":{}";
private String emptyArray = ":[]";
private String newChars = ":null";
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
ResponseBody responseBody = response.body();
if (responseBody != null) {
String json = responseBody.string();
MediaType contentType = responseBody.contentType();
if (!json.contains(emptyString)) {
ResponseBody body = ResponseBody.create(contentType, json);
return response.newBuilder().body(body).build();
} else {
String replace = json.replace(emptyString, newChars);
String replace1 = replace.replace(emptyObject, newChars);
String replace2 = replace1.replace(emptyArray, newChars);
ResponseBody body = ResponseBody.create(contentType, replace2);
return response.newBuilder().body(body).build();
}
}
return response;
}
}
這個注釋好像也挺全的,哈哈...
HttpObserver我放到講api包的時候再講!!!!
bean包下HttpResult類
一般來講,我們的接口請求下來的結(jié)構(gòu)大致都是這樣的
{
"code":"noError",
"data":{
"banner":Array[3]
},
"msg":"",
"result":true
}
接下來看一下我針對這個接口做的HttpResult類
/**
* Created by ziabo on 2017/5/9.
* T就是傳遞過來的data的類型
*/
public class HttpResult<T> {
public String code;
public String msg;
public boolean result;
public T data;
}
這個是要手寫的,下面這個是GsonFormat自動生成的,toString方法是我自己加進去的,方便打印.所有的變量我都聲明為public的方便存取.
/**
* Created by ziabo on 2017/5/9.
* 這個是實體類,里面只有我們關(guān)注的數(shù)據(jù),其他的都統(tǒng)一處理
*/
public class DataBean {
/**
* nextPage : 1
* count : 6
* pageSize : 20
* prevPage : 1
* currentPage : 1
* pageNum : 1
* healthInfo : [{"img":"http://test2.mb.zkrj.com/wlstatic/image/2017-03-30/0394155040297634.png","formatCreateDate":"03-30","formatUpdateDate":"04-01","index":1,"updateTime":"2017-04-01 16:01:44","title":"茶的物極必反","accountId":"4028817d549332dd015494a0edd80000","subTitle":"知識","createTime":"2017-03-30 16:19:34","publish":true,"adminAccountId":"4028817d549332dd015494a0edd80000","orders":1,"id":"8a9a35085b180e49015b1e4c604800ad","account":"zkrj"},{"img":"http://test2.mb.zkrj.com/wlstatic/image/2017-03-30/1143420851997416.jpeg","formatCreateDate":"03-30","formatUpdateDate":"04-01","index":2,"updateTime":"2017-04-01 15:59:24","title":"少食多餐在說什么丹允?","accountId":"4028817d549332dd015494a0edd80000","subTitle":"糖尿病","createTime":"2017-03-30 16:12:03","publish":true,"adminAccountId":"4028817d549332dd015494a0edd80000","orders":1,"id":"8a9a35085b180e49015b1e4581a100aa","account":"zkrj"},{"img":"http://test2.mb.zkrj.com/wlstatic/image/2017-03-30/7490881972133794.jpeg","formatCreateDate":"03-30","formatUpdateDate":"04-01","index":3,"updateTime":"2017-04-01 15:56:22","title":"健康運動踢毽子","accountId":"4028817d549332dd015494a0edd80000","subTitle":"高血壓","createTime":"2017-03-30 16:10:58","publish":true,"adminAccountId":"4028817d549332dd015494a0edd80000","orders":1,"id":"8a9a35085b180e49015b1e4483c400a8","account":"zkrj"},{"img":"http://test2.mb.zkrj.com/wlstatic/image/2017-03-30/8457604241319624.jpeg","formatCreateDate":"03-30","formatUpdateDate":"04-01","index":4,"updateTime":"2017-04-01 15:54:19","title":"糖尿病病足的定義與預(yù)防","accountId":"4028817d549332dd015494a0edd80000","subTitle":"糖尿病","createTime":"2017-03-30 11:59:50","publish":true,"adminAccountId":"4028817d549332dd015494a0edd80000","orders":1,"id":"8a9a35085b180e49015b1d5e9897009a","account":"zkrj"},{"img":"http://test2.mb.zkrj.com/wlstatic/image/2017-03-30/4638045747699966.jpeg","formatCreateDate":"03-27","formatUpdateDate":"04-01","index":5,"updateTime":"2017-04-01 15:50:28","title":"日常小事才不是小事","accountId":"4028817d549332dd015494a0edd80000","subTitle":"高血壓","createTime":"2017-03-27 11:13:05","publish":true,"adminAccountId":"4028817d549332dd015494a0edd80000","orders":1,"id":"8a9a35085b09d7e0015b0dc0b4750005","account":"zkrj"},{"img":"http://test2.mb.zkrj.com/wlstatic/image/2017-04-01/9660687163661661.jpeg","formatCreateDate":"03-27","formatUpdateDate":"04-01","index":6,"updateTime":"2017-04-01 14:57:04","title":"洗澡謹記五個不","accountId":"4028817d549332dd015494a0edd80000","subTitle":"糖尿病","createTime":"2017-03-27 11:10:10","publish":true,"adminAccountId":"4028817d549332dd015494a0edd80000","orders":1,"id":"8a9a35085b09d7e0015b0dbe08e60003","account":"zkrj"}]
*/
public int nextPage;
public int count;
public int pageSize;
public int prevPage;
public int currentPage;
public int pageNum;
public List<HealthInfoBean> healthInfo;
public static class HealthInfoBean {
/**
* img : http://test2.mb.zkrj.com/wlstatic/image/2017-03-30/0394155040297634.png
* formatCreateDate : 03-30
* formatUpdateDate : 04-01
* index : 1
* updateTime : 2017-04-01 16:01:44
* title : 茶的物極必反
* accountId : 4028817d549332dd015494a0edd80000
* subTitle : 知識
* createTime : 2017-03-30 16:19:34
* publish : true
* adminAccountId : 4028817d549332dd015494a0edd80000
* orders : 1
* id : 8a9a35085b180e49015b1e4c604800ad
* account : zkrj
*/
public String img;
public String formatCreateDate;
public String formatUpdateDate;
public int index;
public String updateTime;
public String title;
public String accountId;
public String subTitle;
public String createTime;
public boolean publish;
public String adminAccountId;
public int orders;
public String id;
public String account;
@Override
public String toString() {
return "HealthInfoBean{" +
"img='" + img + '\'' +
", formatCreateDate='" + formatCreateDate + '\'' +
", formatUpdateDate='" + formatUpdateDate + '\'' +
", index=" + index +
", updateTime='" + updateTime + '\'' +
", title='" + title + '\'' +
", accountId='" + accountId + '\'' +
", subTitle='" + subTitle + '\'' +
", createTime='" + createTime + '\'' +
", publish=" + publish +
", adminAccountId='" + adminAccountId + '\'' +
", orders=" + orders +
", id='" + id + '\'' +
", account='" + account + '\'' +
'}';
}
}
@Override
public String toString() {
return "DataBean{" +
"nextPage=" + nextPage +
", count=" + count +
", pageSize=" + pageSize +
", prevPage=" + prevPage +
", currentPage=" + currentPage +
", pageNum=" + pageNum +
", healthInfo=" + healthInfo +
'}';
}
}
當(dāng)我們使用的時候只需要這么拼,就是整個完整的JavaBean
HttpResult<DataBean>
這些網(wǎng)上講的人很多,相信做過的肯定都了解,就不多說了!
api包下面的四個類(以及上面沒有說的HttpObserver)
這里面是整個部分的核心,相對而言也比較難理解,但是理解了以后就會發(fā)現(xiàn)豁然開朗!
首先是ApiInterface
/**
* Created by ziabo on 2017/5/9.
* 不懂的地方可以仔細研究Retrofit
*/
public interface ApiInterface {
/**
* 獲取健康信息
*/
@GET("/rest/app/healthInfo")
Observable<HttpResult<DataBean>> healthInfo(@QueryMap Map<String, Object> map);
}
不要嫌棄我畫工捉急,下面是一個圖解,簡單介紹一下
1 規(guī)定了當(dāng)前的請求方式是GET請求(因為我實在沒有一個合適的接口,此處用的是我一個朋友友情提供的接口,非常感謝)
2 填的是你除了BaseUrl之外的部分
3 此處是與原生的Retrofit區(qū)別比較大的一點,也是精髓之處,對RxJava有了解的肯定知道Observable是個什么東西,這里就不多解釋
4 同上,里面為什么這么寫上面也已經(jīng)解釋過了
5 Retrofit在GET請求時規(guī)定的,不多解釋
6 這個map的key是String,value是Object,你可以放任意數(shù)據(jù)類型
到這里也許有人會問,既然有了接口,那么接口的實現(xiàn)類呢?此處牽扯到Retrofit的原理,大家可以通過這個博客了解一二,四個字,動態(tài)代理!(其實我也不明所以....此處感謝博客的作者 Alexclin ,讓我省了不少力,哈哈)
SchedulersTransformer
顧名思義:調(diào)度器,上完代碼再解釋,此處和RxJava 1.x有很大的不同
/**
* Created by ziabo on 2017/5/9.
* 線程調(diào)度器
*/
public class SchedulersTransformer{
public static <T>ObservableTransformer<T,T> io_main(){
return upstream ->
upstream.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
}
由于代碼有部分Lamada,我大致說一下吧<T>ObservableTransformer<T,T>
這個是我們需要返回的類型,點擊去看源碼是這樣的ObservableTransformer<Upstream, Downstream>
,返回的時候我們new一個ObservableTransformer的時候就會實現(xiàn)他內(nèi)部的apply方法,ObservableSource<Downstream> apply(Observable<Upstream> upstream);
他所做的事情就是把我們輸入進來的Observable做了一些處理,具體做了哪些處理呢?我們具體看代碼,subscribeOn(Schedulers.io())
這句話意思是在io線程建立連接(此處暫時用這個措辭,因為用訂閱老感覺不是很舒服),unsubscribeOn(Schedulers.io())
這一句的意思是在io線程解除連接,observeOn(AndroidSchedulers.mainThread())
這句話的意思是指定回調(diào)線程是Android的主線程,也就是我們常說的UI線程.
HttpResultFunc
這個類也是要針對接口進行編寫的
/**
* Created by ziabo on 2017/5/9.
* 類描述:用來統(tǒng)一處理Http的status,并將HttpResult的data部分剝離出來返回給subscriber
* @param <T> data部分的數(shù)據(jù)模型
*/
public class HttpResultFunc<T> implements Function<HttpResult<T>,T>{
@Override
public T apply(HttpResult<T> tHttpResult) throws Exception {
if (!tHttpResult.result){//假設(shè)當(dāng)結(jié)果為true的時候是請求成功
if (tHttpResult.msg!=null){//請求失敗的情況下吐司錯誤信息
Toast.makeText(App.INSTANCE, tHttpResult.msg, Toast.LENGTH_SHORT).show();
}
}
return tHttpResult.data;
}
}
這個是在RxJava的map操作符里面放的,作用就是剝離公共區(qū)域的數(shù)據(jù)做處理,并且把數(shù)據(jù)轉(zhuǎn)換成我們想要的類型DataBean,這樣在成功的回調(diào)中就只有我們真正關(guān)心的數(shù)據(jù),其他的一些問題都被統(tǒng)一處理了,具體看注釋,我大致是這么寫的,你也可以根據(jù)自己的業(yè)務(wù)邏輯做自己的操作!
ApiService
這個類就是所有準(zhǔn)備工作完了之后的最最核心的地方了,看到這里也許你累了,此時你可以起來活動活動,喝杯咖啡打足精神,整理整理思路之后再來看這里!
/**
* Created by ziabo on 2017/5/9.
* ApiService
*/
public class ApiService {
private ApiInterface mApiInterface;
private ApiService() {
//HTTP log
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
//RequestInterceptor
RequestInterceptor requestInterceptor = new RequestInterceptor();
//ResponseInterceptor
ResponseInterceptor responseInterceptor = new ResponseInterceptor();
//OkHttpClient
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(20, TimeUnit.SECONDS)
.addInterceptor(requestInterceptor)
.addInterceptor(responseInterceptor);
// 通過你當(dāng)前的控制debug的全局常量控制是否打log
if (Constants.DEBUG_MODE) {
builder.addInterceptor(httpLoggingInterceptor);
}
OkHttpClient mOkHttpClient = builder.build();
//Retrofit
Retrofit mRetrofit = new Retrofit.Builder()
.client(mOkHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl("http://test2.mb.zkrj.com/")//替換為你自己的BaseUrl
.build();
mApiInterface = mRetrofit.create(ApiInterface.class);
}
//單例
private static class SingletonHolder {
private static final ApiService INSTANCE = new ApiService();
}
//單例
public static ApiService getApiService() {
return SingletonHolder.INSTANCE;
}
/**
* 獲取健康信息
*/
public void get_health(Observer<DataBean> observer, Map<String, Object> map) {
mApiInterface.healthInfo(map)
.compose(SchedulersTransformer.io_main())
.map(new HttpResultFunc<>())
.subscribe(observer);
}
}
里面把我們之前所有準(zhǔn)備的東西都用上了,Constants
類是我們整個項目里面的常量池!此處我著重介紹一下我下面這個方法!
這次箭頭是不是比上面好看了?哈哈
1 這個是RxJava 2.x中的觀察者,類似于1.x的SubScriber,有興趣的點進去看看就知道了
2 ApiInterface接口的方法的調(diào)用
3 compose操作符,百度一搜一大堆,不多解釋,概念1.x和2.x基本沒有什么變化
4 map操作符,同上
5 建立連接
HttpObserver
這個放在最后講,因為這個是整個框架成型的最后一步!不廢話,直接上代碼
/**
* Created by ziabo on 2017/5/9.
* 結(jié)果回調(diào)回來之后的接口的實現(xiàn)類
* 有興趣的話可以翻閱這里 http://reactivex.io/documentation/observable.html
*/
public abstract class HttpObserver<R> implements Observer<R> {
/**
* 建立鏈接的時候調(diào)用并生成Disposable對象,此處相當(dāng)于1.x的onStart()方法我做了如下處理
* 有更好建議的可以私聊我,或者評論
* @param d 鏈接狀態(tài)對象
*/
@Override
public void onSubscribe(Disposable d) {
if (!NetUtils.isConnected()) {
if (d!=null && !d.isDisposed()){
d.dispose();
}
T.showShort("請檢查網(wǎng)絡(luò)連接后重試!");
onFinished();
}else{
getDisposable(d);
}
}
/**
* 此處和1.x的onNext()基本沒有什么變化,所以我選擇注釋,讓實現(xiàn)類自己處理
* 之前我是寫了的,看過這篇博客的應(yīng)該有印象
* @param r 返回的結(jié)果,沒網(wǎng)絡(luò)時提示
*/
// @Override
// public void onNext(R r) {
// onSuccess(r);
// }
//
// public abstract void onSuccess(R r);
/**
* 出現(xiàn)異常的時候會走這里,我們統(tǒng)一放在 onFinished();處理
*/
@Override
public void onError(Throwable e) {
onFinished();
if (e instanceof HttpException || e instanceof ConnectException || e instanceof SocketTimeoutException || e instanceof TimeoutException){
onNetworkException(e);
}else {
onUnknownException(e);
}
}
/**
* 不管成功與失敗,這里都會走一次,所以加onFinished();方法
*/
@Override
public void onComplete() {
onFinished();
}
/**
* 請求結(jié)束之后的回調(diào),無論成功還是失敗,此處一般無邏輯代碼,經(jīng)常用來寫ProgressBar的dismiss
*/
public abstract void onFinished();
/**
* 向子類暴露 Disposable
*/
public abstract void getDisposable(Disposable disposable);
private void onNetworkException(Throwable e) {
e.printStackTrace();
T.showShort("獲取數(shù)據(jù)失敗彤恶,請檢查網(wǎng)絡(luò)狀態(tài)");
}
private void onUnknownException(Throwable e) {
e.printStackTrace();
}
}
注釋寫的很詳細了,還有很多需要完善的地方,希望大家看到的能夠提出寶貴的意見!
最后再說兩句
這個庫是我一個朋友(流風(fēng)夜雪)自己研究出來的,我只是在此基礎(chǔ)上做了RxJava部分的升級,關(guān)于RxJava2.x還有很多很強大的地方我還沒有用到,有思路的希望給我提一下,在這里先說聲謝謝!
這個庫的好處就是其他地方你都定好了以后,一個新的api,只要知道數(shù)據(jù)結(jié)構(gòu),就只需要做以下兩步:
在ApiInterface中添加接口具體如圖
在ApiService中添加一個方法具體如圖
調(diào)用的時候直接這么寫:
private void getData() {
Map<String,Object> map = new HashMap<>();
map.put("currentPage",1);
map.put("pageSize",20);
//此處的new HttpObserver用了轉(zhuǎn)型,必須要這么寫,要不然里面是四個方法,而且我們自定義的HttpObserver也會顯得毫無用處
ApiService.getApiService().get_health(new HttpObserver<DataBean>() {
@Override
public void onNext(DataBean dataBean) {
T.showShort(dataBean.toString());
Log.d("MainActivity", dataBean.toString());
}
@Override
public void onFinished() {
//不做任何處理
}
@Override
public void getDisposable(Disposable disposable) {
addDisposable(disposable);
}
},map);
}
}
后言:歷時兩天,這個博客終于完結(jié)了!希望大家不要吝嗇起碼給個贊吧,就沖我這排版看起來還不錯呀!
項目源碼已經(jīng)上傳到github,我最近也會不斷做更新,歡迎吐槽!
此處只寫了BaseAvtivity,然而我們實際開發(fā)中不可能不會用到Fragmrnt,而且RxJava是一個容易造成內(nèi)存泄漏的庫,接下來的一段時間我會研究一下rxlifecycle2.x 然后做一個防止內(nèi)存泄漏的較完善的東西!謝謝觀看