2010-12-02 126 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); 

    }