2014-03-07 30 views
2

我有下面的代码位:返回从回调这是坐落在一个异步任务的值doInBackGround

这里是对doucmentation链接FO rthe asyncHttp: Link

这就是调用登录任务:

mAuthTask = new UserLoginTask(); 
mAuthTask.execute((Void) null); 

这里是由Android模板活动提供异步任务:

public class UserLoginTask extends AsyncTask<Void, Void, Boolean> { 
    @Override 
    protected Boolean doInBackground(Void... params) { 
     // TODO: attempt authentication against a network service. 

     Network.login(mEmail, mPassword, new AsyncHttpResponseHandler() { 

      @Override 
      public void onSuccess(int statusCode, Header[] headers, 
        byte[] responseBody) { 

       if (statusCode == 200) { 
        // Successfully got a response 
        for (int i = 0; i < headers.length; i++) { 
         if (headers[i].getName().equalsIgnoreCase("token")) { 
          // Set the token to the received value 
          Network.SetToken(headers[i].getValue()); 
        // >>>>>>>  return true; <<<<<<<<< 
         } 
        } 
       } 
       // >>>>> return false <<<<<<<<<<<< 

      } 

      @Override 
      public void onFailure(int statusCode, Header[] headers, 
        byte[] responseBody, Throwable error) { 
       // Response failed :(
        //  >>>>>>>>>>>>>>>>>> return false <<<<<<<<<<<<< 
      }   
     }); 

     // TODO: register the new account here. 
     return true; 
    } 

    @Override 
    protected void onPostExecute(final Boolean success) { 
     mAuthTask = null; 
     showProgress(false); 

     if (success) { 
      finish(); 
     } else { 
      mPasswordView 
        .setError(getString(R.string.error_incorrect_password)); 
      mPasswordView.requestFocus(); 
     } 
    } 

如何从AsyncHttpResponseHandler中返回true或false,然后将该值返回到异步任务?这样它就可以成功执行它的后处理方法。

我只能想到设置变量,然后封锁它。但是那样就会使它变得异步,我宁愿远离它。

+0

和最新何为问题? – Sanjeev

+1

“AsyncHttpResponseHandler”不是'Network.login'异步吗? –

+0

@ super-qua是的。但我不认为它的成功方法会在用户线程上运行吗?因为我必须在回调中更新UI,并且不允许从工作线程更新ui。 – Zapnologica

回答

1

从开发文档

的AsyncTask能够正确且容易使用的UI线程。该类允许执行后台操作并在UI线程上发布结果,而无需操纵线程和/或处理程序.AsyncTask被设计为围绕线程和处理程序的助手类,并不构成通用线程框架。AsyncTasks应该理想地(最多几秒钟。)可用于短期操作

现在说,如果你真的想在onPostExecute才能完成,你可以做到这一点

public class UserLoginTask extends AsyncTask<Void, Void, Boolean> { 
    @Override 
    protected Boolean doInBackground(Void... params) { 
     // TODO: attempt authentication against a network service. 

     final ResponseContainer responseContainer = new ResponseContainer(); 
     Network.login(mEmail, mPassword, new AsyncHttpResponseHandler() { 

      @Override 
      public void onSuccess(int statusCode, Header[] headers, 
        byte[] responseBody) { 

       if (statusCode == 200) { 
        // Successfully got a response 
        for (int i = 0; i < headers.length; i++) { 
         if (headers[i].getName().equalsIgnoreCase("token")) { 
          // Set the token to the received value 
          Network.SetToken(headers[i].getValue()); 
        // >>>>>>>  return true; <<<<<<<<< 
          responseContainer.result = true; 
         } 
        } 
       } 
       // >>>>> return false <<<<<<<<<<<< 
       responseContainer.result = false; 
      } 

      @Override 
      public void onFailure(int statusCode, Header[] headers, 
        byte[] responseBody, Throwable error) { 
       // Response failed :(
        //  >>>>>>>>>>>>>>>>>> return false <<<<<<<<<<<<< 
       responseContainer.result = false; 
      }   
     }); 

     // TODO: register the new account here. 
     return responseContainer.result; 
    } 

    @Override 
    protected void onPostExecute(final Boolean success) { 
     mAuthTask = null; 
     showProgress(false); 

     if (success) { 
      finish(); 
     } else { 
      mPasswordView 
        .setError(getString(R.string.error_incorrect_password)); 
      mPasswordView.requestFocus(); 
     } 
    } 

    private class ResponseContainer { 
     public boolean result; 
    } 
} 
+0

我有同样的问题比作者,我对@尼尔的答案有点怀疑使用AsyncHttpResponseHandler(接口一般)将被异步执行,所以返回responseContainer.result将在onSuccess或onFailure之前被执行,对吗?或者它确实如此,但这将是意想不到的! – GrayFox

0

当且仅当网络呼叫在其自己的线程上运行时,您可以尝试通过确定网络呼叫使用哪个线程并使用Thread.join来阻止doInBackground来执行此操作。

但是,我不认为你可以保证它会,因为你没有指定执行者,并且可以在你给出的代码之外改变。所以,如果我遇到了这个问题,我会打开代码并使用AsyncHandler来响应网络调用的响应,从而完全避免嵌套的异步操作。类似这样的:

public void loginUser() { 
    Network.login(mEmail, mPassword, new AsyncHttpResponseHandler() { 

     @Override 
     public void onSuccess(int statusCode, Header[] headers, 
       byte[] responseBody) { 

      if (statusCode == 200) { 
       // Successfully got a response 
       for (int i = 0; i < headers.length; i++) { 
        if (headers[i].getName().equalsIgnoreCase("token")) { 
         // Set the token to the received value 
         Network.SetToken(headers[i].getValue()); 
         new RegisterUserTask(statusCode, responseBody).execute(); 
        } 
       } 
      } 
      // respond to a failed authentication. 
      mPasswordView 
       .setError(getString(R.string.error_incorrect_password)); 
      mPasswordView.requestFocus(); 

     } 

     @Override 
     public void onFailure(int statusCode, Header[] headers, 
       byte[] responseBody, Throwable error) { 
      // Response failed :(
       // Show some sort of error. 
     }   
    }); 
} 

public class RegisterUserTask extends AsyncTask<Void, Void, Boolean> { 
    private int statusCode; 
    private byte[] body; 

    public RegisterUserTask(int statusCode, byte[] body) { 
     this.statusCode = statusCode; 
     this.body = body; 
    } 

    @Override 
    protected Boolean doInBackground(Void... params) { 
     // TODO: register the new account here. 

     return true; 
    } 

    @Override 
    protected void onPostExecute(final Boolean success) { 
     mAuthTask = null; 
     showProgress(false); 

     if (success) { 
      finish(); 
     } 
    } 
} 
+0

BUFT会'public void onSuccess('在用户线程上运行吗? – Zapnologica

+1

如果我们正在讨论'android-async-http'库,那么是的。 (在页面顶部)](http://loopj.com/android-async-http/):*“所有的请求都是在你的应用程序的主UI线程之外进行的,但是任何回调逻辑都将在相同的线程作为回调被创建...“* – Menno

+0

那么在这种情况下,这是非常容易的。谢谢你确认 – Zapnologica

0

是不是Network.login已经是异步?

您可以使用处理系统:

private static final int SUCCESS= 0; 
private static final int FAIL= 1; 
//In your class 
    private final Handler handler = new Handler() { 

     @Override 
     public void handleMessage(final Message msg) { 
      runOnUiThread(new Runnable() { 

       @Override 
       public void run() { 
        switch (msg.what) { 
         case SUCCESS: 
          finish(); 
          break; 
         case FAIL: 
          mPasswordView.setError(getString(R.string.error_incorrect_password)); 
          mPasswordView.requestFocus(); 
          break; 
         default: 
          break; 
        } 
       } 
      }); 
     } 
    }; 

    public class UserLoginTask extends AsyncTask<Void, Void, Boolean> { 
     @Override 
     protected Boolean doInBackground(Void... params) { 
      // TODO: attempt authentication against a network service. 

      Network.login(mEmail, mPassword, new AsyncHttpResponseHandler() { 

       @Override 
       public void onSuccess(int statusCode, Header[] headers, 
         byte[] responseBody) { 

        if (statusCode == 200) { 
         // Successfully got a response 
         for (int i = 0; i < headers.length; i++) { 
          if (headers[i].getName().equalsIgnoreCase("token")) { 
           // Set the token to the received value 
           Network.SetToken(headers[i].getValue()); 
           handler.sendEmptyMessage(SUCCESS); 
          } 
         } 
        } 
        // >>>>> return false <<<<<<<<<<<< 
        handler.sendEmptyMessage(FAIL); 
       } 

       @Override 
       public void onFailure(int statusCode, Header[] headers, 
         byte[] responseBody, Throwable error) { 
        // Response failed :(
        handler.sendEmptyMessage(FAIL); 
         //  >>>>>>>>>>>>>>>>>> return false <<<<<<<<<<<<< 
       }   
      }); 

      // TODO: register the new account here. 
      return true; 
     } 

     @Override 
     protected void onPostExecute(final Boolean success) { 

     } 
    } 

但我认为你没有使用的AsyncTask与Network.login .. 如果它时线也许只是一个新的主题?

new Thread() { 
       @Override 
       public void run() { 
        Network.login(...) { 
         ... 
        } 
       }; 
}.start(); 
0

如果我明白你的意思,你的意思是找到一种方法来处理像AsyncTaskCompleted事件,做你的工作人员那里。该解决方案是定义一个接口一样WebServiceCallbackProxy:

public class AsynServiceCall extends AsyncTask<String, Integer, char[]> { 

WebServiceCallbackProxy proxy; 
.... 
public AsynServiceCall(WebServiceCallbackProxy webServiceProxy, ProgressDialog progressDialog) { 
    this.proxy = webServiceProxy; 

} 

然后调用PostExecute您CallBackMethod:

protected void onPostExecute(char[] response) { 
     if (this.progressDialog != null) { 
      progressDialog.dismiss(); 
     } 
     if(proxy != null) 
      proxy.CallBack(response, this.serviceName, this.isCommunicationSucced, this.requestType, this.serivceTicket); 
    } 

这样做,你有

public interface WebServiceCallbackProxy { 

    void CallBack(char[] jsonData, String serviceName, boolean isCommunicationSucceed, HttpRequestType reguestType, String serviceTicket); 
} 

然后在你的AsyncTask定义一个实例具有OnCompleted CallBack方法的AsyncTask。