嵌套的AsyncTask和onPostExecute

3
我正在另一个AsyncTask(2)中使用AsyncTask(1)。 AsyncTask 1获取在线用户数据,计算响应中的条目数,并在onPostExecute中为每个条目显示用户名并运行新的AsyncTask(2)从服务器获取图像并将其加载到ImageView中。所有这些都发生在onPostExecute中。 这一切都很完美,用户数据被获取并显示,每个条目的图像都逐个显示。
但是,对数组进行迭代和在AsyncTask 1的onPostExecute中更新TextView的速度非常快,基本上只显示数组中的最后一个用户名,其他用户名已被加载,但人眼无法检测到:)
同时,AsyncTask 2仍在从网络获取图像,并显示错误用户的个人资料图像。 我在这里遇到的问题显然是这两个任务需要同步。所以我想我只需等待AsyncTask 2中的输出,使用get()方法即可,但现在根本没有更新任何内容,没有TextView...这对我来说是意外的行为。
因此,问题是如何同步这两个AsyncTask?
以下是代码示例,以澄清情况:
    //instantiate first AsyncTask
    new AsyncRequest().execute(bundle);

    private class AsyncRequest extends AsyncTask<Bundle, Void, String> {
    protected String doInBackground(Bundle... bundle) {
        String data = null;
        try {
            data = request(null, bundle[0]); //request the data
            return data;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return data;
    }// end method

    protected void onPostExecute(String response) {
        JSONArray data = null;
        try {
            JSONObject response2 = Util.parseJson(response);
            data        = response2.optJSONArray("data");
            int amount  = data.length();
            TextView s1 = (TextView) findViewById(R.id.some_id);
            s1.setText("" + amount); //displays number of items

            //display the data
            for(int i=0; i<amount; i++){
                String email        = "";
                String id           = "";
                JSONObject json_obj = data.getJSONObject(i);
                Log.d("JSONObject ", ""+json_obj);
                String name         = json_obj.getString("name");
                if (json_obj.has("email")){
                    email           = json_obj.getString("email");
                }
                if (json_obj.has("id")){
                    id          = json_obj.getString("id");
                }
                String picture  = "http://www.domain.com/"+id+"/picture";
                TextView s2     = (TextView) findViewById(R.id.name_placeholder);
                s2.setText(name);
                //here we do a new AsynTask for each entry and wait until the data is fetched
                new DownloadProfileImageTask().execute(picture, name).get(); 
            }
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }// end method
1个回答

8

不太清楚为什么您正在使用多个名称调用单个TextViewsetText。正如您所提到的,尽管您对所有名称进行了setText,但只看到一个名称。也许您需要使用ListView或类似的东西。

现在关于您的问题:可能您不需要两个AsyncTask。您可以在单个AsyncTask中完成所有操作。 代码将类似于以下内容:

//Create a Holder class as a data holder. 
//For simplicity, public attributes are used
class Holder{
  public String name;
  public String email;
  public String id;
  public BitmapDrawable imageDrawable;
}

//instantiate the AsyncTask
new AsyncRequest().execute(bundle);

private class AsyncRequest extends AsyncTask<Bundle, Holder, Integer> {
protected Integer doInBackground(Bundle... bundle) {
    int amount = 0;
    try {
        data = request(null, bundle[0]); //request the data

        JSONArray data = null;
        JSONObject response2 = Util.parseJson(response);
        data        = response2.optJSONArray("data");
        amount  = data.length();

        //display the data
        for(int i=0; i<amount; i++){
            Holder holder = new Holder();
            holder.email        = "";
            holder.id           = "";
            JSONObject json_obj = data.getJSONObject(i);
            Log.d("JSONObject ", ""+json_obj);
            holder.name         = json_obj.getString("name");
            if (json_obj.has("email")){
                holder.email           = json_obj.getString("email");
            }
            if (json_obj.has("id")){
                holder.id          = json_obj.getString("id");
            }
            String picture  = "http://www.domain.com/"+id+"/picture";

            //Fetch the image and create a Drawable from it - Synchronously
            holder.imageDrawable = getImageDrawable(picture, name);

            publishProgress(holder);

        }
    } catch (Exception e) {
        e.printStackTrace();
    } 
    return amount;
}// end method

protected void onProgressUpdate(Holder... holder) {
    //Update the user name and image
    TextView s2     = (TextView) findViewById(R.id.name_placeholder);
    s2.setText(holder[0].name);

    ImageView imgView = (ImageView) findViewById(R.id.imageViewId);
    imgView.setImageDrawable(holder[0].imageDrawable);

}

protected void onPostExecute(Integer amount) {
    TextView s1 = (TextView) findViewById(R.id.some_id);
    s1.setText(amount.toString()); //displays number of items
}// end method

哇,我为什么没想到这个?其实是非常简单的解决方案。非常感谢您抽出时间修改我的代码并将其发布为答案!我需要对它进行一些小修改才能使其正常工作,已经更新了您的答案。再次感谢。 - slinden77
1
PS:我正在更新单个TextView,因为我想在请求中找到的个人资料中显示用户信息。所有这些都在单个页面/活动上完成。当然,稍后我将实际对该活动执行有用的操作;) - slinden77

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接