【发布时间】:2015-11-17 11:42:45
【问题描述】:
我用它来配置我的改造:
RestAdapter restAdapter = new RestAdapter.Builder()
//add headers to requests
.setRequestInterceptor(getAuthenticatedRequestInterceptor())
.setEndpoint(BASE_URL)
.setConverter(new GsonConverter(getGson()))
.build();
并且getAuthenticatedRequestInterceptor() 方法将标头添加到请求中:
public AccountRequestInterceptor getAuthenticatedRequestInterceptor() {
AccountRequestInterceptor interceptor = new AccountRequestInterceptor();
Map<String, String> headers = new HashMap<>();
String accessToken = null;
try {
accessToken = TokenProvider.getInstance(mContext).getToken();
} catch (InterruptedException e) {
}
headers.put(HeadersContract.HEADER_AUTHONRIZATION, O_AUTH_AUTHENTICATION + accessToken);
interceptor.setHeader(headers);
return interceptor;
}
getToken()方法是:
private synchronized string getToken() throws InterruptedException {
if (!isRefreshing()) {
//This is very important to call notify() on the same object that we call wait();
final TokenProvider myInstance = this;
setRefreshing(true);
MyApplication.getRestClient().getAccountService().getRefreshedToken(mLoginData.getRefreshToken())
.subscribe(new Observer<LoginResponse>() {
@Override
public void onCompleted() {
synchronized (myInstance) {
setRefreshing(false);
myInstance.notifyAll();
}
}
@Override
public void onError(Throwable e) {
synchronized (myInstance) {
setRefreshing(false);
myInstance.notifyAll();
}
}
@Override
public void onNext(LoginResponse loginResponse) {
synchronized (myInstance) {
mLoginData = loginResponse;
mAccountProvider.saveLoginData(loginResponse);
myInstance.notifyAll();
}
}
});
}
this.wait();
return mLoginData.getToken();
}
TokenProvider.getInstance(mContext).getToken() 在主线程上有一个wait() 以从异步方法获取响应,我知道这是一件坏事,但我需要在这里等待响应从中获取令牌并然后返回令牌。如何在单独的线程中执行此操作以避免在主线程上等待?
注意:
1 - 在任何带有改造的请求之前调用它。
2 - 我read this 并且我知道我可以在请求失败后刷新令牌,但出于商业原因,我希望避免使用无效令牌。
3 - 我在Activity 中调用MyApplication.getRestClient().getAccountService().login(loginRequest,callback...),在添加令牌之前,一切都发生在后台线程中。所以我想使用我的令牌并且不要阻塞主线程。
更新:我在新的 OkHttp 中添加了以下 Interceptor:
public class RequestTokenInterceptor implements Interceptor {
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
Request newRequest;
try {
Log.d("addHeader", "Before");
String token = TokenProvider.getInstance(mContext).getToken();
if (token != null) {
newRequest = request.newBuilder()
.addHeader("Bearer", token)
.build();
} else {
// I want to cancel the request or raise an exception to catch it in onError method
// of retrofit callback.
}
} catch (InterruptedException e) {
Log.d("addHeader", "Error");
e.printStackTrace();
return chain.proceed(request);
}
Log.d("addHeader", "after");
return chain.proceed(newRequest);
}
}
如果 token 为 null,我现在如何取消请求或引发异常以在改造回调的 onError 方法中捕获它?
【问题讨论】:
-
不要在主线程上发送请求?
-
我在我的活动中使用 MyApplication.getRestClient().getAccountService().login(loginRequest,callback...) 并且在添加令牌之前,一切都发生在后台线程中。
-
@immibis 说了什么,还有stackoverflow.com/questions/22490057/…
标签: java android multithreading retrofit