2010-12-02 122 views
9

我想要使用AsyncTask擴展類來處理連接到URL,解析JSON,解析過程中顯示不確定的ProgressDialog,並返回結果作爲鍵值在HashMap中配對主Activity。 HashMap的結果將被主Activity讀取並放入表單字段中。然而,即使我在我的AsyncTask中填充HashMap(由println語句證明),在主Activity中調用返回HashMap的方法會產生一個空的結果。我無法弄清楚這是我做錯了什麼,或者我誤解了AsyncTask的功能。Android - 從AsyncTask的結果不返回到主活動

我在辯論把我的類擴展AsyncTask到一個Activity。本質上,用戶在這個數據搜索/解析過程中不應該做任何事情,並且應該等到ProgressDialog消失後才能再次與應用程序交互(或者點擊後退按鈕)。另外,我的應用程序需要能夠處理AsyncTask中的異常被捕獲的特定情況(無法連接到URL,錯誤的JSON,無法找到的搜索產品ID)以及針對這些異常定製的自定義錯誤對話框。如果這個類是一個Activity,我可以很容易地做到這一點,因爲我可以在調用finish()時返回不同的結果代碼,具體取決於是否捕獲到異常。

同樣,我不確定AsyncTask是否是最好的解決方案,因爲在收集和分析信息時用戶不會做其他任何事情。請告訴我,如果一個新的活動會有意義,或者如果我只是綁定我的後臺線程的實現。

MainActivity.java

mInitiateProductLookupButton.setOnClickListener(new View.OnClickListener() { 
      public void onClick(View v) { 
       ProductLookup pl = new ProductLookup(id, MainActivity.this); 
       pl.execute(); 

       // The below variable is always empty! 
       HashMap<String, String> productInfo = pl.getProductInfo(); 
       applyProductInfoToFormFields(productInfo); 
      } 
     }); 

ProductLookup.java

public class ProductLookup extends AsyncTask<Object, Void, HashMap<String, String>> { 
    private String mProductID; 
    private Context mContext; 
    HashMap<String, String> mProductInfo; 
    ProgressDialog mDialog; 

    public ProductLookup(String id, Context applicationContext) { 
     mProductID = id; 
     mContext = applicationContext; 
     mProductInfo = new HashMap<String, String>(); 
    } 

    @Override 
    protected void onPreExecute() { 
     mDialog = new ProgressDialog(mContext); 
     mDialog.setMessage("Loading product info. Please wait..."); 
     mDialog.setIndeterminate(true); 
     mDialog.setCancelable(false); 
     mDialog.show(); 
    } 

    @Override 
    protected void onPostExecute(HashMap<String, String> result){ 
     super.onPostExecute(result); 
     mDialog.dismiss(); 
     mProductInfo = result; 
    } 


    @Override 
    protected HashMap<String, String> doInBackground(Object... params) { 
     try { 
      // Connect to URL, parse JSON, and add key-value pairs to mProductInfo... 

     } catch (MalformedURLException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (JSONException e) { 
      e.printStackTrace(); 
     } 
     finally { 
      try { 
       // Close input/output reader variables 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
     return mProductInfo; 

    } 

    public HashMap<String, String> getProductInfo(){ 
     return this.mProductInfo; 
    } 

} 

回答

5

當您發出.execute()運行的線程,並且不等待結果。

因此,無論您在此之後調用它,它都是空的,因爲數據尚未加載。

您需要在PostExecuted結果直接通過二傳手MainActivity.this.setProductInfo(result)

+1

當我嘗試這樣做,我得到的是不會讓我編了一個錯誤:「類型MainActivity沒有外圍實例是可訪問的範圍內」 – Keeb13r 2010-12-02 23:21:17

+2

創建的AsyncTask您的MainActivity內作爲子類的私有。 – Pentium10 2010-12-03 06:24:17

3

有一些對你的思念概念設置爲您的活動。 AsyncTask.execute()之後的語句將在調用之後立即執行。而你的doInBackground在其他線程中執行。在這裏,當您使用productInfo映射時,doInBackground沒有完成,所以結果沒有填充在那裏

簡單的解決方案是使用onPostExecute方法得到的結果。

protected void onPostExecute(HashMap<String, String> result){ 
     mDialog.dismiss(); 
     mProductInfo = result; 
applyProductInfoToFormFields(productInfo); 

    }