2014-03-07 28 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。