我正在嘗試使用Android的AccountManager來處理排球網絡庫,該API用於爲我的REST API獲取身份驗證令牌。我的基本想法是延遲實際的Volley請求(實際上GSSONRequest擴展默認的請求),直到從AccountManager中檢索到令牌(請參閱下面的TokinzedGsonRequest)。然而,這似乎並沒有工作 - GC工作得像瘋了一樣,應用程序最終因Stackoverflow錯誤而崩潰。有任何想法嗎?使用AccountManager令牌對排球請求進行排序
APIClient.java
public static void makeGsonRequest(Activity context, GsonRequest request, RequestQueue requestQueue) {
AccountManager accountManager = AccountManager.get(context);
Account account = getAccount(context, accountManager);
// Delay the request until a token is available
TokenizedGsonRequest futureRequest = new TokenizedGsonRequest(request, requestQueue);
Bundle options = new Bundle();
accountManager.getAuthToken(
account,
context.getResources().getString(R.string.authenticator_auth_type),
options,
context,
futureRequest,
null
);
}
TokenizedGsonRequest.java(實現AccountManagerCallback)
/**
* Wrapper around {@link .helpers.GsonRequest} for use with
* an {@link android.accounts.AccountManager}. The actual {@link com.android.volley.Request}
* is delayed until a token has been obtained.
*/
private static class TokenizedGsonRequest implements AccountManagerCallback<Bundle> {
public static final String TAG = TokenizedGsonRequest.class.getSimpleName();
private GsonRequest mRequest;
private RequestQueue mRequestQueue;
private TokenizedGsonRequest(GsonRequest request, RequestQueue requestQueue) {
this.mRequest = request;
this.mRequestQueue = requestQueue;
}
@Override
public void run(AccountManagerFuture<Bundle> result) {
Bundle bundle;
// todo authentication error
try {
bundle = result.getResult();
} catch (OperationCanceledException e) {
e.printStackTrace();
return;
} catch (AuthenticatorException e) {
e.printStackTrace();
return;
} catch (IOException e) {
e.printStackTrace();
return;
}
String authToken = bundle.getString(AccountManager.KEY_AUTHTOKEN);
if (!TextUtils.isEmpty(authToken)) {
Log.d(TAG, "Received authentication token " + authToken);
try {
// Since Volley request urls are final, we have to copy the existing one
String tokenUrl = API.appendQueryParameter(mRequest.getUrl(), API.TOKEN, authToken);
GsonRequest requestCopy = new GsonRequest<>(
mRequest.getMethod(),
tokenUrl,
mRequest.getClass(),
mRequest.getHeaders(),
mRequest.getRequestObject(),
mRequest.getListener(),
mRequest.getErrorListener() // todo wrap error listener for retry on 400
);
// Retain the original request tag for cancellation
requestCopy.setTag(TAG);
mRequestQueue.add(requestCopy);
} catch (AuthFailureError e) {
Log.d(TAG, e.getMessage());
// todo bubble up
}
} else {
// todo authentication error
}
}
}