無(wú)標(biāo)題.png
package com.jh.jtestone.net;
import android.text.TextUtils;
import com.jh.jtestone.callback.IGlobalManager;
import com.jh.jtestone.net.exception.TokenInvalidException;
import com.jh.jtestone.net.exception.TokenNotExistException;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Function;
/**
* Created by 暗號(hào) on 2017/9/3.
*/
public class ProxyHandler implements InvocationHandler{
private final static String TAG = "Token_Proxy";
private final static String TOKEN = "token";
private final static int REFRESH_TOKEN_VALID_TIME = 30;
private static long tokenChangedTime = 0;
private Throwable mRefreshTokenError = null;
private boolean mIsTokenNeedRefresh;
private Object mProxyObject;
private IGlobalManager iGlobalManager;
public ProxyHandler(Object mProxyObject, IGlobalManager iGlobalManager) {
this.mProxyObject = mProxyObject;
this.iGlobalManager = iGlobalManager;
}
@Override
public Object invoke(Object o, final Method method,final Object[] objects) throws Throwable {
return Observable.just(null).flatMap(new Function<Object, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(@NonNull Object o) throws Exception {
try {
if(mIsTokenNeedRefresh){
updateMethodToken(method,objects);
}
return (Observable<?>) method.invoke(mProxyObject,objects);
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
return null;
}
}).retryWhen(new Function<Observable<Throwable>, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(@NonNull Observable<Throwable> throwableObservable) throws Exception {
return throwableObservable.flatMap(new Function<Throwable, ObservableSource<?>>() {
@Override
public ObservableSource<?> apply(@NonNull Throwable throwable) throws Exception {
if(throwable instanceof TokenInvalidException){
return refreshTokenWhenTokenInvalid();
}else if(throwable instanceof TokenNotExistException){
// Token 不存在膛壹,執(zhí)行退出登錄的操作。(為了防止多個(gè)請(qǐng)求疼电,都出現(xiàn) Token 不存在的問(wèn)題,
// 這里需要取消當(dāng)前所有的網(wǎng)絡(luò)請(qǐng)求)
iGlobalManager.exitLogin();
return Observable.error(throwable);
}
return Observable.error(throwable);
}
});
}
});
}
/**
* Refresh the token when the current token is invalid.
*
* @return Observable
*/
private Observable<?> refreshTokenWhenTokenInvalid() {
synchronized (ProxyHandler.class) {
// Have refreshed the token successfully in the valid time.
if (new Date().getTime() - tokenChangedTime < REFRESH_TOKEN_VALID_TIME) {
mIsTokenNeedRefresh = true;
return Observable.just(true);
} else {
// call the refresh token api.
RetrofitUtil.getInstance().get(IApiService.class).refreshToken().subscribe(new Subscriber<TokenModel>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
mRefreshTokenError = e;
}
@Override
public void onNext(TokenModel model) {
if (model != null) {
mIsTokenNeedRefresh = true;
tokenChangedTime = new Date().getTime();
GlobalToken.updateToken(model.token);
Log.d(TAG, "Refresh token success, time = " + tokenChangedTime);
}
}
});
if (mRefreshTokenError != null) {
return Observable.error(mRefreshTokenError);
} else {
return Observable.just(true);
}
}
}
}
/**
* Update the token of the args in the method.
*
* PS: 因?yàn)檫@里使用的是 GET 請(qǐng)求减拭,所以這里就需要對(duì) Query 的參數(shù)名稱為 token 的方法蔽豺。
* 若是 POST 請(qǐng)求,或者使用 Body 拧粪,自行替換修陡。因?yàn)?參數(shù)數(shù)組已經(jīng)知道,進(jìn)行遍歷找到相應(yīng)的值可霎,進(jìn)行替換即可(更新為新的 token 值)魄鸦。
*/
private void updateMethodToken(Method method, Object[] args) {
if (mIsTokenNeedRefresh && !TextUtils.isEmpty(GlobalToken.getToken())) {
Annotation[][] annotationsArray = method.getParameterAnnotations();
Annotation[] annotations;
if (annotationsArray != null && annotationsArray.length > 0) {
for (int i = 0; i < annotationsArray.length; i++) {
annotations = annotationsArray[i];
for (Annotation annotation : annotations) {
if (annotation instanceof Query) {
if (TOKEN.equals(((Query) annotation).value())) {
args[i] = GlobalToken.getToken();
}
}
}
}
}
mIsTokenNeedRefresh = false;
}
}
}