2012-02-13 64 views
1

即使在閱讀Developer.Android上的所有內容之後,我仍然難以理解AsyncTask。我正在尋找一些我應該如何繼續的見解。這是的情況:擴展AsyncTask時如何以及在哪裏調用我的任務

我有一個活動,onClick事件調用基礎LoginController類的LoginCheck()方法。然後,LoginController類繼續從UserInfo類或Activity(用戶和密碼)獲取所需的任何信息,並創建RestClient的實例,然後調用該Web服務並嘗試登錄。RestClient具有私有類擴展AsyncTask的CallServiceTask。

我在這裏有一些設計問題,我希望你能有所幫助。

  • 我在做對吧?這是否是確保任何對Web服務的調用都是異步完成的正確方法?
  • 如何使用onProgressUpdate或其他方式通知用戶應用程序正在登錄?
  • 我該如何去獲取保存在DoinBackground()中的數據?

下面你會發現有問題的項目的片段:

RESTClient實現

// From the constructor... 
rtnData = new Object[]{ new JSONObject() , Boolean.TRUE }; 

    public void ExecuteCall(RequestMethod method) throws Exception 
{ 
    Object[] parameters = new Object[]{ new HttpGet() , new String("") }; 
    switch(method) { 
     case GET: 
     { 
      //add parameters 
      String combinedParams = ""; 
      if(!params.isEmpty()){ 
       combinedParams += "?"; 
       for(NameValuePair p : params) 
       { 
        String paramString = p.getName() + "=" + URLEncoder.encode(p.getValue()); 
        if(combinedParams.length() > 1) 
        { 
         combinedParams += "&" + paramString; 
        } 
        else 
        { 
         combinedParams += paramString; 
        } 
       } 
      } 

      HttpGet request = new HttpGet(url + combinedParams); 

      //add headers 
      for(NameValuePair h : headers) 
      { 
       request.addHeader(h.getName(), h.getValue()); 
      } 
      parameters[0] = request; 
      parameters[1] = url; 

      new CallServiceTask().execute(request, url); 


      jsonData = ((JSONObject) rtnData[0]).optJSONObject("data"); 
      connError = (Boolean) rtnData[1]; 
      break; 

     } 
     case POST: .... 

    } 
} 

private Object[] executeRequest(HttpUriRequest request, String url) 
{ 
    HttpClient client = new DefaultHttpClient(); 
    client = getNewHttpClient(); 

    HttpResponse httpResponse; 

    try { 
     httpResponse = client.execute(request); 
     HttpEntity entity = httpResponse.getEntity(); 

     if (entity != null) { 

      InputStream instream = entity.getContent(); 
      String response = convertStreamToString(instream); 
      try { 
       rtnData[0] = new JSONObject(response); 
       rtnData[1] = false; 

      } catch (JSONException e1) { 
       rtnData[1] = true; 
       e1.printStackTrace(); 
      } 

      // Closing the input stream will trigger connection release 
      instream.close(); 
     } 

    } catch (ClientProtocolException e) { 
     client.getConnectionManager().shutdown(); 
     e.printStackTrace(); 
    } catch (IOException e) { 
     client.getConnectionManager().shutdown(); 
     e.printStackTrace(); 
    } 
    return rtnData; 
} 

CallServiceTask

private class CallServiceTask extends AsyncTask<Object, Void, Object[]> 
{ 

    protected Object[] doInBackground(Object... params) 
    { 
     HttpUriRequest req = (HttpUriRequest) params[0]; 
     String url = (String) params[1]; 

     return executeRequest(req, url); 
    } 

    @Override 
    protected void onPostExecute(Object[] result) 
    { 
      rtnData = result; 
    } 
} 

回答

2

這是絕對正確的,任何可能長時間運行操作應該是exe在單獨的線程中被關閉。 AsyncTask是解決這類問題的好方法,因爲它還爲您提供了一種簡單的方法來將您的任務與UI線程同步。這是你第一個問題的答案。

現在,關於UI線程更新以向用戶顯示您的應用程序未被卡住。由於AsyncTaskonPreExecute()和方法在UI線程內運行,因此您可以輕鬆地在那裏創建,運行和停止ProgressDialogProgressBar。如果要顯示任務的當前進度,應在doInBackground()內調用publishProgress(int)方法,然後在AsyncTaskonProgressUpdate()方法內使用該方法。例如,您可以更新您的ProgressDialog

爲了從AsyncTask中獲得結果,您可以調用它的get()方法(這是一個同步調用),或者實現某種回調接口,它將告訴活動該任務已完成。

我希望答案很清楚,如果沒有,請隨時提出更多問題。希望這可以幫助。

EDIT

創建名爲onFetchFinishedListener的接口,例如,與一種方法 - void onFetchFinished(String)。您的活動啓動AsyncTask,必須實現此界面。現在在您的AsyncTask內部創建一個構造函數,將OnFetchFinishedListener對象作爲參數,並在您的活動中實例化AsyncTask時,發送對Activity作爲參數的引用(因爲它實現了OnFetchFinishedListener)。然後當你的任務完成doInBackground()裏面的活動onFetchFinished()。現在在ActivityonFetchFinished(String)方法中,您可以使用帶回調的String(或其他對象)。再次,希望我很清楚。

+0

你的回答很有幫助,但在我的腦海裏仍然留下了幾個問題。我一直在閱讀諸如「在UI線程上運行」之類的東西,並在UI線程中運行。這是否意味着我可以在CallServiceTask類中從OnPreExecute內簡單地調用像ProgressDialog這樣的東西,UI元素將自動出現在屏幕上? 現在至於回調界面,這一切聽起來很希臘我。我將不得不進一步瞭解它:) – CodePrimate 2012-02-13 11:47:32

+0

@litemode,1)是的,你可以在onPreExecute()和onPostExecute()方法內創建類似於Dialogs的東西,2)我將嘗試編輯我的答案來解釋一下回調接口。 – Egor 2012-02-13 13:23:09

相關問題