从 AsyncTask 一次下载一个项目

Download one item at a time from AsyncTask

我有一个片段 GridViewImageViews 作为项目。单元格数量约为 25。

对于每张图片,我都有一个 Id 请求的服务器。所以它的 25 个服务器请求。需要 2-3 秒。

我怎样才能一次接收一张图片并将其动态设置为单元格的内容?每个没有图片的单元格都应该包含ProgressBar.

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


码码

片段的onCreate():

@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:

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 适配器:

    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

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()

调用
@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
    */
}

然后您需要将异步任务更改为

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

您也不想在 AsyncTask 上调用 .get() 因为 it is a blocking call

与此类似的内容应该可以满足您的需求。

备选方案

不过,有很多libraries that can do the work for you and give you benefits

@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 中

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

    }

对于进度条我觉得你做的是对的 更换适配器 class 的

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

getView 方法内部

  @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;
    }

}