Java 在异步任务内使用ListenableFuture Azure调用
我对Android、Java和Azure有点陌生,我正在使用Azure MobileServiceClient类尝试在我的后端调用各种API。我遇到的问题是MobileServiceClient的方法似乎都是异步的,使用ListenableFutures 这很好,只是我想在助手类中使用这些方法,该类还可以做其他应该是异步的事情(因此它扩展了AsyncTask)。但是,由于MobileServiceClient调用是异步的,因此会导致AsyncTask过早返回。我希望AsyncTask在MobileServiceClient方法返回之前不要调用其onPostExecute方法 我如何避免这个问题?我需要改变我的架构吗?是否可以将MobileServiceClient调用放在另一个异步任务中并让它阻止它Java 在异步任务内使用ListenableFuture Azure调用,java,android,azure,asynchronous,Java,Android,Azure,Asynchronous,我对Android、Java和Azure有点陌生,我正在使用Azure MobileServiceClient类尝试在我的后端调用各种API。我遇到的问题是MobileServiceClient的方法似乎都是异步的,使用ListenableFutures 这很好,只是我想在助手类中使用这些方法,该类还可以做其他应该是异步的事情(因此它扩展了AsyncTask)。但是,由于MobileServiceClient调用是异步的,因此会导致AsyncTask过早返回。我希望AsyncTask在Mobil
@Override
protected Boolean doInBackground(Void... params) {
Log.i(TAG, "Doing background task");
if(mTaskType==tTaskType.LOGIN_TASK){
login();
//do other stuff here that should be async
}
return true;
}
private void login(){
Log.i(TAG, "Doing login task...");
ListenableFuture<JsonElement> result = mClient.invokeApi("login", mJSONHelper.makeLoginObject(thisUser));
Futures.addCallback(result, new FutureCallback<JsonElement>() {
@Override
public void onFailure(Throwable exc) {
error.setError(ErrorHelper.Error.NETWORK_ERROR);
}
@Override
public void onSuccess(JsonElement result) {
}
});
}
@覆盖
受保护的布尔doInBackground(Void…params){
Log.i(标记“执行后台任务”);
如果(mTaskType==tTaskType.LOGIN\u任务){
登录();
//在这里做其他应该是异步的事情
}
返回true;
}
私有void登录(){
i(标记“正在执行登录任务…”);
ListenableFuture result=mClient.invokeApi(“login”,mJSONHelper.makeLoginObject(thisUser));
Futures.addCallback(结果,newfuturecallback(){
@凌驾
公共失效失效失效(可丢弃的exc){
error.setError(ErrorHelper.error.NETWORK_error);
}
@凌驾
成功时公共无效(JsonElement结果){
}
});
}
好吧,我是用一面旗子做的——虽然不好看。我仍然对任何更优雅或正确的方法感兴趣。或者这真的是正确的方法吗
private void login(){
Log.i(TAG, "Doing login task...");
isLoginFinished= false;
ListenableFuture<JsonElement> result = mClient.invokeApi("login", mJSONHelper.makeLoginObject(thisUser));
Futures.addCallback(result, new FutureCallback<JsonElement>() {
@Override
public void onFailure(Throwable exc) {
error.setError(ErrorHelper.Error.NETWORK_ERROR);
isLoginFinished= true;
}
@Override
public void onSuccess(JsonElement result) {
Log.i(TAG, "Login call was successful, parsing result:" + result.toString());
isLoginFinished= true;
}
});
while(!isLoginFinished);
}
private void login(){
i(标记“正在执行登录任务…”);
isLoginFinished=false;
ListenableFuture result=mClient.invokeApi(“login”,mJSONHelper.makeLoginObject(thisUser));
Futures.addCallback(结果,newfuturecallback(){
@凌驾
公共失效失效失效(可丢弃的exc){
error.setError(ErrorHelper.error.NETWORK_error);
isLoginFinished=true;
}
@凌驾
成功时公共无效(JsonElement结果){
i(标记“登录调用成功,解析结果:”+result.toString());
isLoginFinished=true;
}
});
而(!isLoginFinished);
}
我将在序言中提出警告,我对Android也不是很熟悉。然而,根据我在其他平台上的经验和对API的快速搜索,我认为您应该采用这种方法。我也不保证代码片段会编译,因为我还没有检查过,但它们应该已经接近编译了
您的login
方法应该返回一个ListenableFuture
,然后doInBackground
方法可以添加自己的回调,该回调在登录完成时执行
如果您希望其他内容能够等待doInBackground
任务完成,那么还应该返回一个ListenableFuture
,可以使用Futures.transform
方法将一系列异步调用链接在一起
我认为它应该是这样的:
protected void doInBackground(Void... params) {
Log.i(TAG, "Doing background task");
if(mTaskType==tTaskType.LOGIN_TASK){
var loginFuture = ListenableFuture<UserDetail> login();
Futures.addCallback(loginFuture, new FutureCallback<UserDetail>() {
@Override
public void onSuccess(UserDetail userDetail)
{
// do other stuff here that should be async
// also optionally you could implement this as a transform
// style thing to and return another future from this `doInBackground`
// method so other parts of your code could know when it is completed.
}
@Override
public void onFailure(Throwable exc) {
// I'd quite likely move the error handling from the login method here
// as that way it can also handle any exceptions caused by the transform
// from json to user detail as well.
}
})
}
}
private ListenableFuture<UserDetail> login(){
Log.i(TAG, "Doing login task...");
ListenableFuture<JsonElement> loginFutureResult = mClient.invokeApi("login", mJSONHelper.makeLoginObject(thisUser));
Futures.addCallback(loginFutureResult, new FutureCallback<JsonElement>() {
@Override
public void onFailure(Throwable exc) {
// This is just to keep with what your style is, for recording the error
// I think you might be better off handling it at a higher level and
// also you might want to check `exc` to see if it was an actual network
// error and not for example just failed credentials or something.
error.setError(ErrorHelper.Error.NETWORK_ERROR);
}
@Override
public void onSuccess(JsonElement result) {
Log.i(TAG, "The login was successful");
}
});
// lets pretend that instead of returning the JSON response
// you wanted to map it to a user detail before returning, just to show how to do that.
AsyncFunction<JsonElement, UserDetail> transformUserJsonFunction =
new AsyncFunction<JsonElement, UserDetail>() {
public ListenableFuture<UserDetail> apply(JsonElement userJson) {
// some code to map the json element to user detail
UserDetail userDetail = new UserDetail(userJson);
return Futures.immediateFuture(userDetail);
}
};
return Futures.transform(loginFutureResult, transformUserJsonFunction);
}
受保护的void doInBackground(void…params){
Log.i(标记“执行后台任务”);
如果(mTaskType==tTaskType.LOGIN\u任务){
var loginFuture=ListenableFuture login();
Futures.addCallback(loginFuture,newfuturecallback(){
@凌驾
成功时的公共void(UserDetail UserDetail)
{
//在这里做其他应该是异步的事情
//还可以选择将其实现为转换
//从这个“做的事”的背景中创造出另一个未来`
//方法,以便代码的其他部分可以知道它何时完成。
}
@凌驾
失效时的公共无效(可丢弃的exc){
//我很可能会将错误处理从登录方法移到这里
//这样,它还可以处理由转换引起的任何异常
//从json到用户详细信息。
}
})
}
}
私有ListenableFuture登录(){
i(标记“正在执行登录任务…”);
ListenableFuture loginFutureResult=mClient.invokeApi(“login”,mJSONHelper.makeLoginObject(thisUser));
Futures.addCallback(loginFutureResult,newfuturecallback(){
@凌驾
公共失效失效失效(可丢弃的exc){
//这只是为了保持你的风格,记录错误
//我认为你最好从更高的层次和更高的层次来处理它
//另外,您可能需要检查'exc',看看它是否是一个实际的网络
//错误,而不仅仅是失败的凭证或其他东西。
error.setError(ErrorHelper.error.NETWORK_error);
}
@凌驾
成功时公共无效(JsonElement结果){
Log.i(标记“登录成功”);
}
});
//让我们假设它不是返回JSON响应
//您希望在返回之前将其映射到用户详细信息,只是为了演示如何执行此操作。
AsyncFunction transformUserJsonFunction=
新的异步函数(){
public ListenableFuture应用(JsonElement userJson){
//一些将json元素映射到用户详细信息的代码
UserDetail UserDetail=新的UserDetail(userJson);
返回期货。即时期货(用户详细信息);
}
};
return Futures.transform(loginFutureResult,transformUserJsonFunction);
}
我希望这为您指明了正确的方向。这将使您的一个处理器内核保持100%的性能,直到网络呼叫完成,因为它处于一个紧密的循环中。谢谢Caleb,这无疑为我指明了正确的方向。它看起来像是一个小男孩