嵌套的AsyncTask和onPostExecute [英] nested AsyncTask and onPostExecute

查看:178
本文介绍了嵌套的AsyncTask和onPostExecute的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是的AsyncTask (1)在另一的AsyncTask (2)。
AsyncTask的1获取在线用户数据,统计条目数的响应,并为每个条目,在 onPostExecute 显示用户名和运行一个新的AsyncTask(2)取一个形象从一台服务器,并加载它变成一个的ImageView 。这一切都发生在 onPostExecute
这是工作完美,用户数据被取出,并示出,并且该图像示逐个对每个条目

然而,通过阵列的itteration和的的TextView 的AsyncTask 1的 onPostExecute 如此之快,它基本上只显示数组中的最后一个用户名,其他的人被加载,但无法与人眼检测:)

同时,的AsyncTask 2还是从网上获取的图像,并显示了错误的用户个人资料图片。
我显然这里的问题是这2需要保持同步。
所以我想我只是等待输出的AsyncTask 2的的get()方法,但现在没有更新在所有了,没有的TextView ...这是意外的行为对我来说。

所以,问题是如何将2 的AsyncTask S'同步

code位澄清,如果它仍然需要

  //实例第一的AsyncTask
    新AsyncRequest()执行(包);    私有类AsyncRequest扩展的AsyncTask<捆绑,太虚,字符串> {
    保护字符串doInBackground(包...束){
        字符串数据= NULL;
        尝试{
            数据=请求(NULL,捆绑[0]); //请求数据
            返回的数据;
        }赶上(FileNotFoundException异常五){
            e.printStackTrace();
        }赶上(MalformedURLException的E){
            e.printStackTrace();
        }赶上(IOException异常五){
            e.printStackTrace();
        }
        返回的数据;
    } // end方法    保护无效onPostExecute(字符串响应){
        JSONArray数据= NULL;
        尝试{
            JSONObject的响应2 = Util.parseJson(响应);
            数据= response2.optJSONArray(数据);
            INT金额= data.length();
            TextView的S1 =(的TextView)findViewById(R.id.some_id);
            s1.setText(量+); //显示项目数            //显示数据
            的for(int i = 0; I<金额;我++){
                字符串email =;
                字符串ID =;
                JSONObject的json_obj = data.getJSONObject(I)
                Log.d(JSONObject的,+ json_obj);
                字符串名称= json_obj.getString(名称);
                如果(json_obj.has(电子邮件)){
                    电子邮件= json_obj.getString(电子邮件);
                }
                如果(json_obj.has(ID)){
                    ID = json_obj.getString(ID);
                }
                字符串图片=htt​​p://www.domain.com/\"+id+\"/picture;
                TextView的S2 =(的TextView)findViewById(R.id.name_placeholder);
                s2.setText(名);
                //这里我们做一个新的AsynTask每个条目,等待数据被取出
                新DownloadProfileImageTask()执行(照片,姓名)获得();
            }
        }赶上(JSONException E){
            e.printStackTrace();
        }赶上(InterruptedException的E){
            e.printStackTrace();
        }赶上(为ExecutionException E){
            e.printStackTrace();
        }
    } // end方法


解决方案

它为什么要叫的setText 单是不太清楚的TextView 有多个名字的名字。正如你所提到的,虽然你有的setText 所有的名字,你只能看到一个名字。可能是你需要使用的ListView 或类似的东西。

现在关于你的问题:也许你并不需要两个的AsyncTask 秒。您可以在一个单一的的AsyncTask 做的一切。在code将类似下面:

  //创建一个Holder类作为数据持有人。
//为简单起见,公共属性用来
类持有人{
  公共字符串名称;
  公共字符串的电子邮件;
  公共字符串ID;
  公共BitmapDrawable imageDrawable;
}//实例化AsyncTask的
新AsyncRequest()执行(包);私有类AsyncRequest扩展的AsyncTask<捆绑,持有人,整数GT; {
保护整数doInBackground(包...束){
    INT量= 0;
    尝试{
        数据=请求(NULL,捆绑[0]); //请求数据        JSONArray数据= NULL;
        JSONObject的响应2 = Util.parseJson(响应);
        数据= response2.optJSONArray(数据);
        量= data.length();        //显示数据
        的for(int i = 0; I<金额;我++){
            持有人持有人=新的持有人();
            holder.email =;
            holder.id =;
            JSONObject的json_obj = data.getJSONObject(I)
            Log.d(JSONObject的,+ json_obj);
            holder.name = json_obj.getString(名称);
            如果(json_obj.has(电子邮件)){
                holder.email = json_obj.getString(电子邮件);
            }
            如果(json_obj.has(ID)){
                holder.id = json_obj.getString(ID);
            }
            字符串图片=htt​​p://www.domain.com/\"+id+\"/picture;            //获取图像并创建它可绘制 - 同步方式
            holder.imageDrawable = getImageDrawable(照片,姓名);            publishProgress(保持器);        }
    }赶上(例外五){
        e.printStackTrace();
    }
    返回金额;
} // end方法保护无效onProgressUpdate(持有人持有...){
    //更新的用户名和图像
    TextView的S2 =(的TextView)findViewById(R.id.name_placeholder);
    s2.setText(架[0]。名称);    ImageView的imgView =(ImageView的)findViewById(R.id.imageViewId);
    imgView.setImageDrawable(架[0] .imageDrawable);}保护无效onPostExecute(整数金额){
    TextView的S1 =(的TextView)findViewById(R.id.some_id);
    s1.setText(amount.toString()); //显示项目数
} // end方法

I am using a AsyncTask (1) in another AsyncTask (2). AsyncTask 1 fetches online user data, counts the number of entries in the response and for each entry, in onPostExecute displays a username and runs a new AsyncTask (2) to fetch a image from a server and load it into a ImageView. This all happens in onPostExecute. This is working flawlessly, the user data is fetched and shown, and the images are shown one by one for each entry.

However, the itteration through the array and the updating of the TextView in AsyncTask 1's onPostExecute happens so fast, it basically only shows the last user name in the array, the other ones are loaded, but impossible to detect with the human eye :)

Meanwhile, AsyncTask 2 is still fetching images from online, and showing profile images for the wrong users. The problem I have here obviously, is these 2 need to be in sync. So I thought I just wait for the output in AsyncTask 2 with the get() method, but now nothing is updated at all anymore, no TextView...this is unexpected behaviour for me.

So, the question is how to sync the 2 AsyncTasks?

bit of code to clarify, if it's still needed

    //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

解决方案

It is not quite clear why you are calling setText of the single TextView with the name of multiple names. As you have mentioned, although you had setText of all the names, you only see a single name. May be you need to use a ListView or something like that.

Now regarding your question: probably you don't need two AsyncTasks. You can do everything in a single AsyncTask. The code will be something like below:

//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

这篇关于嵌套的AsyncTask和onPostExecute的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆