关于android:一次从AsyncTask下载一项

Download one item at a time from AsyncTask

我有一个片段,其中GridViewImageViews作为项目。单元格的数量大约为25。

对于每个图像,我都有ID的服务器请求。因此,它有25个服务器请求。耗时2-3秒。

如何一次接收一张图像并将其动态设置为单元格内容?每个没有图像的单元格都应包含ProgressBar

我现在拥有什么:我正在尝试在AsyncTask中加载项目并将Bitmap数组返回到UI线程。但是我不知道如何为每个图像执行此操作。我的GridView仅在下载了所有图像之后出现。并且应该首先显示25个元素,这些元素包含ProgressBars并且没有图像。

代码代码

片段的onCreate()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
public void onCreate(Bundle savedInstanceState) {
    ...

    mItems = new Bitmap[dataChannelsList.size()];

    try {
    //starting AsyncTask
        mItems = new LoadImageAsyncTask(dataChannelsList).execute().get();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
}

LoadImageAsyncTask

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
private class LoadImageAsyncTask extends AsyncTask<Bitmap[], Void, Bitmap[]> {
    private ArrayList<DataChannels> dataChannelsList;
    private Bitmap[] bitmapList;

    public LoadImageAsyncTask(ArrayList<DataChannels> dataChannelsList) {
        this.dataChannelsList = dataChannelsList;

        bitmapList = new Bitmap[dataChannelsList.size()];
    }

    protected void onPreExecute() {
        super.onPreExecute();
    }

    protected Bitmap[] doInBackground(Bitmap[]... params) {
        for (int i = 0; i < dataChannelsList.size(); i++) {
            bitmapList[i] = getChannelImg(dataChannelsList.get(i).getId());
        }
        return bitmapList;
    }


    protected void onPostExecute(Bitmap[] param) {
        super.onPostExecute(param);
    }

    private Bitmap getChannelImg(String id) {
        ...returns Bitmap image by id
    }

}

GridView适配器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
    public class GridViewAdapter extends BaseAdapter {
    private Context mContext;
    private Bitmap[] mItems;

    public GridViewAdapter(Context context, Bitmap[] items) {
        mContext = context;
        mItems = items;
    }

    @Override
    public int getCount() {
        return mItems.length;
    }

    @Override
    public Object getItem(int position) {
        return mItems[position];
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;

        if (convertView == null) {
            // inflate the GridView item layout
            LayoutInflater inflater = LayoutInflater.from(mContext);
            convertView = inflater.inflate(R.layout.gridview_item, parent, false);

            // initialize the view holder
            viewHolder = new ViewHolder();
            viewHolder.ivIcon = (ImageView) convertView.findViewById(R.id.imageview_channelIcon);
            viewHolder.progressBar = (ProgressBar) convertView.findViewById(R.id.progress_bar_load_image);
            convertView.setTag(viewHolder);
        } else {
            // recycle the already inflated view
            viewHolder = (ViewHolder) convertView.getTag();
        }

        // update the item view
        Bitmap item = mItems[position];

        //hide progress bar and bring image to top
        viewHolder.progressBar.setVisibility(View.GONE);
        viewHolder.ivIcon.setImageBitmap(item);
        return convertView;
    }

}

private static class ViewHolder {
    ImageView ivIcon;
    ProgressBar progressBar;
}

伙计们,我真的需要您的帮助。告诉是否需要更多代码或解释。


您可以为此使用publishProgress()来调用onProgressUpdate()

所以在您的for loop中,类似

1
2
3
4
5
6
7
8
for (int i = 0; i < dataChannelsList.size(); i++) {
        // create a variable for the current bitmap
        Bitmap curBitmap = getChannelImg(dataChannelsList.get(i).getId());
        // add it to your list
        bitmapList[i] = curBitmap;
        // and pass it along
        publishProgress(curBitmap);
    }

然后您将需要覆盖onProgressUpdate(),由publishProgress()

调用

1
2
3
4
5
6
@Override
public void onProgressUpdate(Bitmap...progress) {
    /* add the bitmap to your list you're using for your adapter here
     * and call notifyDataSetChanged() on your adapter
    */
}

然后,您需要将asynctask更改为

1
private class LoadImageAsyncTask extends AsyncTask<Bitmap[], Bitmap, Bitmap[]> {

您也不想在AsyncTask上呼叫.get(),因为它是阻塞呼叫

与此类似的东西应该可以为您提供所需的东西。

替代品

但是,有许多库可以为您完成工作并为您带来收益。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Override
public void onCreate(Bundle savedInstanceState) {
    ...

    mItems = new Bitmap[dataChannelsList.size()];
    GridView grid=// declare your gridview;
GridViewAdapter adapter=new GridViewAdapter(activityname.this,mItems);
grid.setAdapter(adapter);

    try {
    //starting AsyncTask here

    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
}

和assynctask

1
2
3
4
5
6
7
protected void onPostExecute(Bitmap[] param) {
        super.onPostExecute(param);
         adapter.notifydatasetchanged;

// adapter should be declared as class variable,so that it can be used here.or else pass adapter variable as actual parameter to assynctask constructor

    }

对于进度条,我认为您正在做的事是正确的
更改适配器类的

1
2
3
4
@Override
    public int getCount() {
        return 25;// the size you want
    }

在getView方法内部

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
  @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;

int currentposition=position;
        if (convertView == null) {
            // inflate the GridView item layout
            LayoutInflater inflater = LayoutInflater.from(mContext);
            convertView = inflater.inflate(R.layout.gridview_item, parent, false);

            // initialize the view holder
            viewHolder = new ViewHolder();
            viewHolder.ivIcon = (ImageView) convertView.findViewById(R.id.imageview_channelIcon);
            viewHolder.progressBar = (ProgressBar) convertView.findViewById(R.id.progress_bar_load_image);
           viewHolder.ivIcon.setTag(currentposition);
            convertView.setTag(viewHolder);
        } else {
            // recycle the already inflated view
            viewHolder = (ViewHolder) convertView.getTag();
        }

        // update the item view
        Bitmap item = mItems[position];

        //hide progress bar and bring image to top

if(Integer.parseInt(viewHolder.ivIcon.getTag().toString())>mItems.size()){
        viewHolder.progressBar.setVisibility(View.VISIBLE);
 viewHolder.ivIcon.setVisibility(View.VISIBLE);
}
else{
viewHolder.progressBar.setVisibility(View.INVISIBLE);
 viewHolder.ivIcon.setVisibility(View.INVISIBLE);

}
        viewHolder.ivIcon.setImageBitmap(item);
        return convertView;
    }

}