从AsyncTask一次下载一个项目

时间:2015-03-26 14:06:23

标签: android gridview android-fragments android-asynctask

我有一个GridView的片段,ImageViews作为项目。细胞数量约为25。

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

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

我现在拥有什么:我正在尝试在AsyncTask中加载项目并将Bitmap数组返回给UI线程。但我不知道如何为每张图片做到这一点。我的GridView仅在下载所有图像后出现。它应该首先显示25个包含ProgressBars和没有图像的元素。


代码

片段的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;
}

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

2 个答案:

答案 0 :(得分:3)

您可以使用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
    */
}

然后您需要将asynctask更改为

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

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

类似的东西应该能给你你想要的东西。

替代方案

但是,有很多libraries that can do the work for you and give you benefits

答案 1 :(得分:1)

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

和asynctask

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

    }

进度条我认为你在做什么是正确的 更改你的适配器类

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

}