我使用这个来配置我的改装:
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-我读了这篇文章,我知道我可以在请求失败后刷新令牌,但出于业务原因,我希望避免出现无效令牌。
3-我在我的activity
中调用MyApplication.GetRestClient().GetAccountService().Login(loginRequest,Callback...)
并且在添加令牌之前,所有事情都发生在后台线程中。所以我想使用我的令牌,不要阻塞主线程。
更新:我在新的OKHTTP中添加了以下拦截器
:
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,我如何取消请求或在reverfit回调的onError方法中引发一个异常来捕获它呢?
这是一个有点奇怪的问题,但让我试着帮你。:)
正如您所知,您可以使用响应拦截器在一个失败请求后通过修改刷新令牌。
让我们尝试在请求之前使用拦截器。
public class RequestTokenInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
// Here where we'll try to refresh token.
// with an retrofit call
// After we succeed we'll proceed our request
Response response = chain.proceed(request);
return response;
}
}
在创建api时,创建一个新的HttpClient:
OkHttpClient client = new OkHttpClient();
client.interceptors().add(new RequestTokenInterceptor());
并将http客户端添加到适配器,如下所示:
.setClient(new OkClient(client))
如果这样做有效,在每个请求之前,您将尝试首先刷新令牌,然后继续您的api请求。所以在ui中,与正常的api调用没有区别。
编辑:
我也在编辑我的答案。如果要在令牌为空的情况下返回一个else大小写中的错误,则可以在else大小写中创建自定义响应:
private Response(Builder builder) {
this.request = builder.request;
this.protocol = builder.protocol;
this.code = builder.code;
this.message = builder.message;
this.handshake = builder.handshake;
this.headers = builder.headers.build();
this.body = builder.body;
this.networkResponse = builder.networkResponse;
this.cacheResponse = builder.cacheResponse;
this.priorResponse = builder.priorResponse;
}
也可以简单地返回空响应。如果您构建自定义响应并将代码设置为不是200,例如401或400+,您将在改型的callbacks failure方法中收到该响应。你想做什么就做什么。
如果您返回null,我想您将得到一个RuntimeException,并且仍然可以在回调的failure方法中捕获响应。
在else中创建自己的响应后,您可以创建自定义回调,捕获空响应,并按需要转换自定义错误,如下所示:
public abstract class DefaultRequestCallback<T> implements Callback<T> {
public abstract void failure(YourCustomException ex);
public abstract void success(T responseBean);
@Override
public void success(T baseResponseBean, Response response) {
if (response == null) {
// Here we catch null response and transform it to our custom Exception
failure(new YourCustomException());
}
} else {
success(baseResponseBean);
}
}
@Override
public void failure(RetrofitError error) {
// Here's your failure method.
// Also you can transform default retrofit errors to your customerrors
YourCustomException ex = new YourCustomException();
failure(ex);
}
}
我想这能帮你。
编辑2:
您可以像下面这样构建一个新的响应。在Response类中有一个builder模式。你可以从那里查。
Response response = new Response.Builder().setCode(401).setMessage("Error Message").build();
问题内容: 我遇到的问题是,有时我启动的线程在调用它之前就完成了。看来这使我的程序等待不再发生的事情()。如何确保不等待线程完成? 问题答案: 如果您阅读JavaDocs for Thread,它将告诉您 永远不要在Thread对象上使用。您应该使用join()
我刚开始使用Selenium Web驱动程序测试一个网上银行交易应用程序。 我喜欢,但有些事让我很恼火。假设我使用以下代码访问登录屏幕: 我也试过: 但这没有帮助,因为这行似乎只有在页面完全加载时才执行。 编辑:我和这里的一个人谈过了..他告诉我ipinvite.iperceptions.com不是我们的应用程序调用的。!!!事实上,当我在FF中加载站点时,我没有看到这个调用?! Selenium
问题内容: 我正在尝试编写一个JS代码,如果给定的数字已经存在于数据库中,它将取消“ btn_submit”按钮.onclick事件。我使用AJAX向数据库查询给定的编号,并确定是否应将数据发送到将上传问题的.php站点。为了确定这一点,我需要numOfRows变量的值,但是因为我在AJAX中将其设置为0,所以validation()函数将在我的AJAX查询完成之前完成,这将导致始终表示给定数字不
问题内容: 更新记录时,我反复出现锁定超时超出异常的情况。 我正在使用Java Struts 2.1 Hibernate配置。使用的数据库是MYSQL。 任何人都知道如何解决它。 问题答案: 这里有一些建议: “ 锁定等待超时 ”通常发生在事务正在等待要更新的数据行上,而该行已被某些其他事务锁定时。 在大多数情况下,问题出在数据库方面。可能的原因可能是表格设计不当,数据量大,约束等。 请查看这个详
问题内容: 我找不到如何测量线程等待锁定的时间。我必须确定一个线程是否正在等待锁定超过1秒,如果需要,则运行另一个线程。谢谢! 问题答案: 试试这个:
我打算在主线程中启动2个线程,主线程应该等到所有2个子线程完成,我就是这样做的。 在上面的代码中,确实让主线程等待子线程,但问题是,在第一个线程完成之前不会创建第二个线程。这不是我想要的。 我想要的是,这两个线程立即在主线程中创建,然后主线程等待它们完成。似乎做不到,是吗? 我想,也许我可以通过一个信号灯来完成这项工作,但还有别的方法吗?