前言
從我最開始用rx和retrofit.到現(xiàn)在,快3年了.
這個庫的內(nèi)容,算是沉淀下來的東西.
個人用這個做過的項目也有很多個了.和項目中用的有點區(qū)別.
因為不能隨便重構(gòu)的原因,比項目里的更好.哈哈.
目錄:
初始化:
NetWorkManager.init(String baseUrl, Application context)
難點1 BaseBean:
作為一個庫,這個類是一個頭疼的問題.因為強耦合.
我們一般寫的baseBaen都是這樣的:
class BaseBean<T>{
String code;
T data;
String msg;
}
不同的人,有不同的協(xié)議,字段名會不一樣,如果用這樣的,明顯是不行的.
這個庫是這樣的(ParseInfo):
你只需要定義自己的basebean規(guī)則,即可
例子
NetWorkManager.addParseInfo(
new RxParseInfo("code", "data", "msg", "200") //200代表成功時的code.
);
這里傳入的參數(shù)都是key的名字.
目前支持3個key值.我覺得基本夠用了.
codeKey
判斷成功
dataKey
返回數(shù)據(jù)
msgKey
服務(wù)器返回消息
庫是如何判斷接口請求成功的
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的請求.我個人覺得是可以滿足大部分的需求了.
如果滿足不了.就寫點定制的就好了.有人會覺得這么寫不行,實際上,我就用這個已經(jīng)寫了很多項目了.
有人會問,為什么這里都是Observable<String>
,往后面看就知道了.嘿嘿
RetrofitUtil
這里使用了餓漢式懶加載單例.
public class RetrofitUtil {
/**
* 服務(wù)器地址
*/
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()
//攔截并設(shè)置緩存
.addNetworkInterceptor(new CacheInterceptor())
//攔截并設(shè)置緩存
.addInterceptor(new CacheInterceptor())
.cache(new Cache(mContext.getCacheDir(), 10240 * 1024));
// 設(shè)置代理
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();
}
}
可以設(shè)置緩存,添加代理,重置baseurl
對Retrofit.create創(chuàng)建的實體類,進行了緩存.
看了半天,先來個例子吧:
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
先來張目錄圖
再來張代碼
這里為什么要寫JsonArrayParesTransformer
和JsonParesTransformer
.
因為在組件化的時候,跨組件GSON解析時,泛型是會丟失的.我不知道現(xiàn)在解決沒.
所以使用這兩個來統(tǒng)一解析結(jié)果.
如果你細心就會發(fā)現(xiàn).JApi
的方法,的返回參數(shù)都是Observable<String>
也就是統(tǒng)一先用String接收結(jié)果,然后再解析成最終結(jié)果.
看到這里,你滿足了嗎? 我是不滿足的.哈哈
難點2 取消網(wǎng)絡(luò)請求
如何舒服的取消請求回調(diào)一直是個頭疼的問題
不取消就會內(nèi)存泄露,調(diào)用已關(guān)閉的activity,造成崩潰.
當(dāng)然,現(xiàn)在有RxLifecyle
之類的庫,很方便.
這里我簡單實現(xiàn)了一個.不過有版本限制.依賴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);
}
}
實現(xiàn)了JApi
,LifecycleObserver
,ObservableTransformer
LifecycleObserver
是為了利用現(xiàn)在android自帶的Lifecycle實現(xiàn)取消回調(diào)
ObservableTransformer
是為了轉(zhuǎn)換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 {
}
});
添加加密/解密
NetWorkManager.initKey("私鑰", "公鑰");//加密解密
設(shè)置超時時間
NetWorkManager.setDefaultTimeOut(20);//秒
設(shè)置重試次數(shù)
NetWorkManager.setDefaultRetry(5);//重試次數(shù)
設(shè)置全局異常統(tǒng)一回調(diào)
NetWorkManager.setExceptionListener(new onExceptionListener() {
@Override
public String onError(Throwable throwable) {
return null;
}
});
設(shè)置添加全局code狀態(tài)處理
NetWorkManager.setApiCallBack(new APICallBack() {
@Override
public String callback(String code, String resultData) {
JsonElement jsonElement = JSONFactory.parseJson(resultData);
return JSONFactory.getValue(jsonElement, "message");
}
});
設(shè)置打開服務(wù)器返回msg異常
如果callback不處理,并打開isOpenApiException,則拋出服務(wù)器返回msg信息
NetWorkManager.setOpenApiException(true);
異常的處理邏輯
String errorMsg = null;
//通過code獲取注冊的接口回調(diào).
APICallBack apiCallback = NetWorkManager.getApiCallback();
if (apiCallback != null) {
String callbackMsg = apiCallback.callback(code, response);
if (!TextUtils.isEmpty(callbackMsg)) {
errorMsg = callbackMsg;
}
}
//如果callback不處理,并打開isOpenApiException,則拋出服務(wù)器返回msg信息
if (TextUtils.isEmpty(errorMsg) && NetWorkManager.isOpenApiException()) {
errorMsg = msg;
}
//拋出異常,走到onError.
throw new APIException(code, errorMsg);
解析結(jié)果是Object或Array的例子:
//結(jié)果是一個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 {
}
});
//結(jié)果是集合
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
,添加當(dāng)前的Disposable
,用于取消回調(diào),如果你用了上面的
JApiImpl
,那么這里可以不傳CompositeDisposable
,這個是我最早實現(xiàn)統(tǒng)一取消回調(diào)的邏輯.
/**
* @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) {
}
@Override
public void onComplete() {
}
public abstract void call(@NonNull T t);
}
ToastObserver
在實際使用的時候,我們一般不會每個請求都彈Toast.
所以.如果需要默認彈Toast的請求.可以使用這個類.
/**
* @author jlanglang 2016/11/14 17:32
*/
public abstract class ToastObserver<T> extends SimpleObserver<T> {
public ToastObserver() {
this(null);
}
public ToastObserver(CompositeDisposable com) {
super(com);
}
@Override
public void onError(Throwable e) {
String errorMsg = NetWorkErrorFactory.disposeError(e);
if (!TextUtils.isEmpty(errorMsg)) {
Toast.makeText(NetWorkManager.getContext(), errorMsg, Toast.LENGTH_SHORT).show();
}
}
}
異常解析工廠
這個類,其實讓我很糾結(jié),因為這個類好像沒什么作用.又好像又作用.
但是太繞了.
比如在NetWorkTransformer
中拋出的APIException
,以及初始化設(shè)置的onExceptionListener
都是這里來處理的.
但不調(diào)用這個方法.這個方法就無意義.
我是在上面的ToastObserver
中調(diào)用了這個方法.
你可以自定義這個方法在哪調(diào)用.
/**
* 異常時處理工廠
*
* @param throwable 異常
* @return 獲取異常提示消息
*/
public static String disposeError(Throwable throwable) {
Class<? extends Throwable> throwableClass = throwable.getClass();
//處理Api自定義異常處理,請求是成功的,如果需要特殊處理,使用APICallBack
if (throwableClass.equals(APIException.class)) {
return throwable.getMessage();
}
//處理error異常,http異常
onExceptionListener exceptionListener = NetWorkManager.getExceptionListener();
if (exceptionListener != null) {
return exceptionListener.onError(throwable);
}
return "";
}
結(jié)語
大致使用就這些了.
庫里還包含了rxbus.
歡迎大家點贊,留言提建議
github地址: JRxRetrofit
交流群:
Flutter:782978118
Android:493180098