1. 程式人生 > >Retrofit2+Rxjava2+okHttp 網路框架封裝

Retrofit2+Rxjava2+okHttp 網路框架封裝

說明

RxJava的概念其實很模糊,我對它的理解就是一個給你方便處理非同步問題的框架,到底有多方便,體會過才知道。。。

Retrofit就是對okhttp做了一層封裝。把網路請求都交給給了Okhttp,我們只需要通過簡單的配置就能使用retrofit來進行網路請求了,Retrofit 除了提供了傳統的 Callback 形式的 API,還有 RxJava 版本的 Observable 形式 API。

自己整理資料當做筆記

一,需要新增的依賴包

 compile 'io.reactivex.rxjava2:rxjava:2.0.7'
    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    compile 'com.squareup.okhttp3:okhttp:3.5.0'
    compile 'com.squareup.okhttp3:logging-interceptor:3.6.0'
    compile 'com.jakewharton:butterknife:8.4.0'

二、網上找了一個url練習具體是http://gank.io/api/data/福利/10/1 

1.根據返回引數,封裝一個基類baseresult (根據實際情況而定)

package com.example.rxjavaretrofit.base;

/**
 * Created by fg on 2017/7/25.
 * 解析實體基類
 */

public class BaseResult<T> {
    private static int SUCCESS_CODE=000000;//成功的code
    private int code;
    private String message;
    private T results;
    private boolean error;

    public boolean isSuccess(){
        return getCode()==SUCCESS_CODE;
    }
    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getResults() {
        return results;
    }

    public void setResults(T results) {
        this.results = results;
    }

    public boolean isError() {
        return error;
    }

    public void setError(boolean error) {
        this.error = error;
    }

    @Override
    public String toString() {
        return super.toString();
    }
}

2.把result內的返回資料  通過GsonFormet工具生成實體類 Bean

package com.example.rxjavaretrofit.bean;

/**
 * Created by 付剛 on 2018/7/25.
 */

public class MeiZiBean {

    /**
     * _id : 5b50107f421aa917a31c0565
     * createdAt : 2018-07-19T12:15:59.226Z
     * desc : 2018-07-19
     * publishedAt : 2018-07-19T00:00:00.0Z
     * source : web
     * type : 福利
     * url : https://ww1.sinaimg.cn/large/0065oQSqly1ftf1snjrjuj30se10r1kx.jpg
     * used : true
     * who : lijinshanmx
     */

    private String _id;
    private String createdAt;
    private String desc;
    private String publishedAt;
    private String source;
    private String type;
    private String url;
    private boolean used;
    private String who;

    public String get_id() {
        return _id;
    }

    public void set_id(String _id) {
        this._id = _id;
    }

    public String getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(String createdAt) {
        this.createdAt = createdAt;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public String getPublishedAt() {
        return publishedAt;
    }

    public void setPublishedAt(String publishedAt) {
        this.publishedAt = publishedAt;
    }

    public String getSource() {
        return source;
    }

    public void setSource(String source) {
        this.source = source;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public boolean isUsed() {
        return used;
    }

    public void setUsed(boolean used) {
        this.used = used;
    }

    public String getWho() {
        return who;
    }

    public void setWho(String who) {
        this.who = who;
    }
}

如果需要實現序列化進行傳值 可實現Parcelable或者Serializable介面

3.接下來我們就要開始介面了哦,回到我們上面的ApiService介面模擬一個API介面getMeiZi() 可以返回得到一個observable<Object>。 

package com.example.rxjavaretrofit.network;

import com.example.rxjavaretrofit.base.BaseResult;
import com.example.rxjavaretrofit.bean.MeiZiBean;

import java.util.List;

import io.reactivex.Observable;
import retrofit2.http.GET;


/**
 * Created by fg on 2018/7/25.
 */

public interface ApiServise {

    //網路請求超時時間 單位毫秒
    int DEFAULT_TIMEOUT=20000;

    String HOST = "http://gank.io/";
    String API_SERVER_URL = HOST + "api/data/";

    @GET("福利/10/1")
    Observable<BaseResult<List<MeiZiBean>>> getMeiZi();


}

4.就是對自己的Retrofit去進行封裝設定

(1)retrofit是基於okhttp的加強版,所以第一步去自定義一個okhttpclient,裡面設定兩個攔截器,一個是日誌攔截器,用於對日誌的篩選,還一個就是網路攔截器,用於對網路請求頭的總體設定。

package com.example.rxjavaretrofit.Utils;

import android.util.Log;

import java.io.IOException;

import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;


/**
 * Created by fg on 2018/7/25.
 * *@description 攔截器工具類
 */

public class InterceptorUtil {

    public static String TAG="----";
    //日誌攔截器
    public static HttpLoggingInterceptor LogInterceptor(){
        return new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
            @Override
            public void log(String message) {
                Log.w(TAG, "log: "+message );
            }
        }).setLevel(HttpLoggingInterceptor.Level.BODY);//設定列印資料的級別
    }

    public static Interceptor HeaderInterceptor(){
        return   new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request mRequest=chain.request();
                //在這裡你可以做一些想做的事,比如token失效時,重新獲取token
                //或者新增header等等,PS我會在下一篇文章總寫攔截token方法
                return chain.proceed(mRequest);
            }
        };

    }

}

(2)建立一個觀察者基類,在其中進行對請求錯誤的封裝和對進度條顯示與消失的封裝。

package com.example.rxjavaretrofit.base;

import android.accounts.NetworkErrorException;
import android.content.Context;


import com.example.rxjavaretrofit.widget.ProgressDialog;

import java.net.ConnectException;
import java.net.UnknownHostException;
import java.util.concurrent.TimeoutException;

import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;

/**
 * Created by fg on 2018/7/25.
 * Observer的封裝
 */

public abstract class BaseObserver<T> implements Observer<BaseResult<T>> {
    protected Context mContext;

    public BaseObserver(Context cxt) {
        this.mContext = cxt;
    }

    public BaseObserver() {

    }

    @Override
    public void onSubscribe(Disposable d) {
        onRequestStart();

    }

    @Override
    public void onNext(BaseResult<T> tBaseEntity) {
        onRequestEnd();
        if (tBaseEntity.isSuccess()) {
            try {
                onSuccees(tBaseEntity);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            try {
                onCodeError(tBaseEntity);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onError(Throwable e) {
//        Log.w(TAG, "onError: ", );這裡可以列印錯誤資訊
        onRequestEnd();
        try {
            if (e instanceof ConnectException
                    || e instanceof TimeoutException
                    || e instanceof NetworkErrorException
                    || e instanceof UnknownHostException) {
                onFailure(e, true);
            } else {
                onFailure(e, false);
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }

    @Override
    public void onComplete() {
    }

    /**
     * 返回成功
     *
     * @param t
     * @throws Exception
     */
    protected abstract void onSuccees(BaseResult<T> t) throws Exception;

    /**
     * 返回成功了,但是code錯誤
     *
     * @param t
     * @throws Exception
     */
    protected void onCodeError(BaseResult<T> t) throws Exception {
    }

    /**
     * 返回失敗
     *
     * @param e
     * @param isNetWorkError 是否是網路錯誤
     * @throws Exception
     */
    protected abstract void onFailure(Throwable e, boolean isNetWorkError) throws Exception;

    protected void onRequestStart() {
    }

    protected void onRequestEnd() {
        closeProgressDialog();
    }

    public void showProgressDialog() {
        ProgressDialog.show(mContext, false, "請稍後");
    }

    public void closeProgressDialog() {
        ProgressDialog.cancle();
    }


}

(3)然後要建立Retrofit例項,構建一個請求的基類

package com.example.rxjavaretrofit.base;

import com.example.rxjavaretrofit.Utils.InterceptorUtil;
import com.example.rxjavaretrofit.network.ApiServise;

import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by fg on 2018/7/25.
 */

public class BaseRequest {
    //retrofit底層用的okHttp,所以設定超時還需要okHttp
    //然後設定5秒超時
    //其中DEFAULT_TIMEOUT是我這邊定義的一個常量
    //TimeUnit為java.util.concurrent包下的時間單位
    //TimeUnit.SECONDS這裡為秒的單位
    OkHttpClient client=new OkHttpClient.Builder()
            .connectTimeout(20, TimeUnit.SECONDS)//設定連線超時時間
            .readTimeout(20, TimeUnit.SECONDS)//設定讀取超時時間
            .writeTimeout(20, TimeUnit.SECONDS)//設定寫入超時時間
            .addInterceptor(InterceptorUtil.HeaderInterceptor())//新增其他攔截器
            .addInterceptor(InterceptorUtil.LogInterceptor())//新增日誌攔截器
            .build();
    Retrofit retrofit = new Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create()) //新增Gson轉換器
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//新增Rx轉換器
            .baseUrl(ApiServise.API_SERVER_URL) //baseurl
            .client(client)
            .build();
    public ApiServise apiServise = retrofit.create(ApiServise.class);

    private static BaseRequest instance;

    public static synchronized BaseRequest getInstance(){
        if(instance == null)
            instance = new BaseRequest();
        return instance;
    }

    public ApiServise getService() {
        return apiServise;
    }
}

OK這時候就可以跑通了讓我們看看完整的請求 (observable(被觀察者)和observer(觀察者)相訂閱)

public void getData() {
        BaseRequest.getInstance().getService()
                .getMeiZi()
                .subscribeOn(Schedulers.newThread())
                .subscribe(new BaseObserver<List<MeiZiBean>>(this) {
                    @Override
                    protected void onSuccees(BaseResult<List<MeiZiBean>> t) throws Exception {
                        List<MeiZiBean> results = t.getResults();
                        Log.e("fff",results.size()+"");

                    }

                    @Override
                    protected void onFailure(Throwable e, boolean isNetWorkError) throws Exception {
                        Log.e("fff",e.toString());
                    }
                });


    }

那麼到這裡,封裝基本上大功告成了,但是上面可以成功解析。後續資料處理就不做敘述了,