Android 個人Retrofit+Rxjava封裝,不搞花裏胡俏

前言

從我最開始用rx和retrofit.到如今,快3年了.android

這個庫的內容,算是沉澱下來的東西.git

我的用這個作過的項目也有不少個了.和項目中用的有點區別.github

由於不能隨便重構的緣由,比項目裏的更好.哈哈.json

目錄:

初始化:

NetWorkManager.init(String baseUrl, Application context)
複製代碼

難點1 BaseBean:

做爲一個庫,這個類是一個頭疼的問題.由於強耦合.api

咱們通常寫的baseBaen都是這樣的:緩存

class BaseBean<T>{
  String code;
  T data;
  String msg;
}
複製代碼

不一樣的人,有不一樣的協議,字段名會不同,若是用這樣的,明顯是不行的.bash

這個庫是這樣的(ParseInfo):

你只須要定義本身的basebean規則,便可服務器

例子

NetWorkManager.addParseInfo(
                new RxParseInfo("code", "data", "msg", "200") //200表明成功時的code.
        );

複製代碼

這裏傳入的參數都是key的名字.網絡

目前支持3個key值.我以爲基本夠用了.app

codeKey判斷成功

dataKey返回數據

msgKey服務器返回消息

庫是如何判斷接口請求成功的

ParseInfo 裏默認經過判斷successCode與返回的codeKey的值進行比較的

public boolean isSuccess(JsonObject asJsonObject) {
        if (checkSuccess != null) {
            return checkSuccess.isSuccess(asJsonObject);
        }
        String code = asJsonObject.get(codeKey).toString();
        return TextUtils.equals(code, successCode);
    }
複製代碼

也能夠自定義判斷是否請求成功

ParseInfo使用setCheckSuccess().非必須.主要是爲了擴展.

new ParseInfo("code", "data", "msg", "200")
 .setCheckSuccess(new ParseInfo.CheckSuccess() {
                    @Override
                    public boolean isSuccess(JsonObject asJsonObject) {
                        return false;
                    }
                })
複製代碼

請求:

public interface JApi {

    /**
     * 上傳文件
      */
    @POST
    @Multipart
    Observable<String> post(@Url String url, @PartMap HashMap<String, RequestBody> params);

    /**
     * 通用POST
     *
     */
    @POST
    Observable<String> post(@Url String url, @Body String json);

    /**
     * 通用POST
     */
    @POST
    Observable<String> post(@Url String url, @Body SimpleParams json);

    /**
     * 通用get
     */
    @GET
    Observable<String> get(@Url String url, @QueryMap SimpleParams params);

}
複製代碼

這裏寫了4個通用的retrofit的請求.我我的以爲是能夠知足大部分的需求了.

若是知足不了.就寫點定製的就行了.有人會以爲這麼寫不行,實際上,我就用這個已經寫了不少項目了.

有人會問,爲何這裏都是Observable<String>,日後面看就知道了.嘿嘿

RetrofitUtil

這裏使用了餓漢式懶加載單例.

public class RetrofitUtil {
    /**
     * 服務器地址
     */
    private static String API_HOST;
    private static Application mContext;
    private static final HashMap<Class, Object> apis = new HashMap<>();

    @SuppressWarnings("unchecked")
    public static <T> T getApi(Class<T> c) {
        Object o = apis.get(c);
        if (null == o) {
            o = getInstance().create(c);
            apis.put(c, o);
        }
        return (T) o;
    }

    public static synchronized void init(String baseUrl, Application context) {
        if (TextUtils.isEmpty(baseUrl)) {
            return;
        }
        mContext = context;
        API_HOST = baseUrl;
        Instance.retrofit = Instance.getRetrofit();
        apis.clear();
    }

    public static Retrofit getInstance() {
        return Instance.retrofit;
    }

    private static class Instance {
        private static Retrofit retrofit = getRetrofit();

        private static Retrofit getRetrofit() {
            OkHttpClient.Builder client = new OkHttpClient.Builder()
                    //攔截並設置緩存
                    .addNetworkInterceptor(new CacheInterceptor())
                    //攔截並設置緩存
                    .addInterceptor(new CacheInterceptor())
                    .cache(new Cache(mContext.getCacheDir(), 10240 * 1024));
            // 設置代理
            if (NetWorkManager.getProxy() != null) {
                client.proxy(NetWorkManager.getProxy());
            }

            for (Interceptor i : NetWorkManager.mInterceptors) {
                client.addInterceptor(i);
            }
            if (BuildConfig.DEBUG) {
                HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
                interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
                client.addInterceptor(interceptor);
            }
            return new Retrofit.Builder()
                    .client(client.build())
                    .baseUrl(API_HOST)
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .build();
        }
    }

複製代碼

能夠設置緩存,添加代理,重置baseurl

對Retrofit.create建立的實體類,進行了緩存.

看了半天,先來個例子吧:

Disposable login = RetrofitUtil.getApi(JApi.class)
                .get("/login", SimpleParams.create()
                        .putP("key1", 1)
                        .putP("key2", 2)
                        .putP("key3", 2)
                        .putP("key4", 3)
                )
                .compose(JRxCompose.normal())
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {

                    }
                });
複製代碼

一個簡單的請求就是這樣的.

有人看了會問, JRxCompose是啥?

JRxCompose

先來張目錄圖

再來張代碼

這裏爲何要寫JsonArrayParesTransformerJsonParesTransformer.

由於在組件化的時候,跨組件GSON解析時,泛型是會丟失的.我不知道如今解決沒.

因此使用這兩個來統一解析結果.

若是你細心就會發現.JApi的方法,的返回參數都是Observable<String>

也就是統一先用String接收結果,而後再解析成最終結果.


看到這裏,你知足了嗎? 我是不知足的.哈哈

難點2 取消網絡請求

如何舒服的取消請求回調一直是個頭疼的問題

不取消就會內存泄露,調用已關閉的activity,形成崩潰.

固然,如今有RxLifecyle之類的庫,很方便.

這裏我簡單實現了一個.不過有版本限制.依賴Android自帶的Lifecycle

JApiImpl

public class JApiImpl implements JApi, LifecycleObserver, ObservableTransformer<String, String> {

    public static JApi getApi() {
        return RetrofitUtil.getApi(JApi.class);
    }

    public static JApiImpl with(Lifecycle lifecycle) {
        JApiImpl JApiImpl = new JApiImpl();
        lifecycle.addObserver(JApiImpl);
        return JApiImpl;
    }

    public static JApiImpl with(Fragment fragment) {
        return with(fragment.getLifecycle());
    }

    public static JApiImpl with(AppCompatActivity activity) {
        return with(activity.getLifecycle());
    }

    private Disposable disposable;

    @Override
    public ObservableSource<String> apply(Observable<String> upstream) {
        return upstream.doOnSubscribe(disposable -> this.disposable = disposable);
    }

    private void cancel() {
        if (this.disposable != null && !disposable.isDisposed()) {
            disposable.dispose();
        }
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    public void onDestroy() {
        this.cancel();
        Log.i("233", "取消了請求");
    }

    @Override
    public Observable<String> post(String url, HashMap<String, RequestBody> params) {
        return getApi().post(url, params).compose(this);
    }

    @Override
    public Observable<String> post(String url, String json) {
        return getApi().post(url, json).compose(this);
    }

    @Override
    public Observable<String> post(String url, SimpleParams params) {
        return getApi().post(url, params).compose(this);
    }

    @Override
    public Observable<String> get(String url, SimpleParams params) {
        return getApi().post(url, params).compose(this);
    }

}

複製代碼

實現了JApi,LifecycleObserver,ObservableTransformer

LifecycleObserver是爲了利用如今android自帶的Lifecycle實現取消回調

ObservableTransformer是爲了轉換Observer.拿到Disposable.

這麼改一下後.請求就能夠這樣:

JApiImpl.with(this)
                .get("/login", SimpleParams.create()
                        .putP("key1", 1)
                        .putP("key2", 2)
                        .putP("key3", 2)
                        .putP("key4", 3)
                )
                .compose(JRxCompose.normal())
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {

                    }
                });
複製代碼

設置添加全局code狀態處理

NetWorkManager.setApiCallBack(new APICallBack() {
            @Override
            public String callback(String code, String resultData) {
                JsonElement jsonElement = JSONFactory.parseJson(resultData);
                return JSONFactory.getValue(jsonElement, "message");
            }
        });
複製代碼

添加加密/解密

NetWorkManager.initKey("私鑰", "公鑰");//加密解密
複製代碼

設置超時時間

NetWorkManager.setDefaultTimeOut(20);//秒
複製代碼

設置重試次數

NetWorkManager.setDefaultRetry(5);//重試次數
複製代碼

解析結果是Object或Array的例子:

//結果是一個Object
        JApiImpl.with(this)
                .post("/Login", SimpleParams.create())
                .compose(JRxCompose.obj(Login.class))
                .subscribe(new Consumer<Login>() {
                    @Override
                    public void accept(Login login) throws Exception {

                    }
                });
        //結果是集合
        JApiImpl.with(this)
                .post("/Login", SimpleParams.create())
                .compose(JRxCompose.array(Login.class))
                .subscribe(new Consumer<List<Login>>() {
                    @Override
                    public void accept(List<Login> logins) throws Exception {
                        
                    }
                });
複製代碼

簡單的Observer

這裏支持傳入CompositeDisposable,添加當前的Disposable,用於取消回調,若是你用了上面的 JApiImpl,那麼這裏能夠不傳CompositeDisposable,這個是我最先實現統一取消回調的邏輯.

/**
 * @author jlanglang  2016/11/14 17:32
 * @版本 2.0
 * @Change
 */
public abstract class SimpleObserver<T> implements Observer<T> {
    protected Disposable mDisposable;
    private CompositeDisposable mCompositeDisposable;

    public SimpleObserver() {
        this(null);
    }

    public SimpleObserver(CompositeDisposable compositeDisposable) {
        mCompositeDisposable = compositeDisposable;
    }

    @Override
    public void onSubscribe(@NonNull Disposable d) {
        mDisposable = d;
        try {
            mCompositeDisposable.add(d);
        } catch (Exception ignored) {

        }
    }

    @Override
    public void onNext(T t) {
        call(t);
    }

    @Override
    public void onError(Throwable e) {
      JErrorEnum.normal(e);
    }


    @Override
    public void onComplete() {

    }

    public abstract void call(@NonNull T t);
}

複製代碼

異常的處理邏輯

String errorMsg = null;
                    //經過code獲取註冊的接口回調.
                    APICallBack apiCallback = NetWorkManager.getApiCallback();
                    if (apiCallback != null) {
                        String callbackMsg = apiCallback.callback(code, response);
                        if (!TextUtils.isEmpty(callbackMsg)) {
                            errorMsg = callbackMsg;
                        }
                    }
                    //若是callback不處理,則拋出服務器返回msg信息
                    if (TextUtils.isEmpty(errorMsg)) {
                        errorMsg = msg;
                    }
                    //拋出異常,走到onError.
                    throw new APIException(code, errorMsg);
複製代碼

異常消息處理

這裏寫了一個枚舉.用來處理異常消息.

public enum JErrorEnum implements Consumer<Throwable> {
    normal(0), toast(1);

    private int type;

    JErrorEnum(int type) {
        this.type = type;
    }

    public static void normal(Throwable throwable) {
        normal.accept(throwable);
    }

    public static void toast(Throwable throwable) {
        toast.accept(throwable);
    }

    @Override
    public void accept(Throwable throwable) {
        String errMsg = "";
        Class<? extends Throwable> throwableClass = throwable.getClass();
        //處理Api自定義異常處理,請求是成功的,若是須要特殊處理,使用APICallBack
        if (throwableClass.equals(APIException.class)) {
            errMsg = throwable.getMessage();
        }
        //處理error異常,http異常
        onExceptionListener exceptionListener = NetWorkManager.getExceptionListener();
        if (exceptionListener != null) {
            errMsg = exceptionListener.onError(throwable);
        }
        if (type == 1 && !TextUtils.isEmpty(errMsg)) {
            Toast.makeText(NetWorkManager.getContext(), errMsg, Toast.LENGTH_SHORT).show();
        }
    }
}
複製代碼

你能夠用如下幾種方式使用:

SimpleObserver

normal默認只處理異常邏輯,不會彈消息

@Override
  public void onError(Throwable e) {
     JErrorEnum.normal(e);
 }
複製代碼

ToastObserver

toast會彈消息

@Override
  public void onError(Throwable e) {
     JErrorEnum.toast(e);
 }
複製代碼

直接用

Disposable subscribe = JApiImpl.with(this)
                .get("", SimpleParams.create())
                .compose(JRxCompose.obj(Login.class))
                .subscribe(login1 -> {

                }, JErrorEnum.toast);
複製代碼

若是不使用JErrorEnum的話.下面的設置就會失效,注意一個請求內不要重複使用哈.

設置全局異常統一回調

NetWorkManager.setExceptionListener(new onExceptionListener() {
            @Override
            public String onError(Throwable throwable) {
                return null; 
            }
        });
複製代碼

結語

大體使用就這些了.

庫裏還包含了rxbus.

歡迎你們點贊,留言提建議

github地址: JRxRetrofit

交流羣:

Flutter:782978118

Android:493180098

相關文章
相關標籤/搜索