简体   繁体   English

从AsyncTask一次下载一项

[英]Download one item at a time from AsyncTask

I have a fragment with GridView with ImageViews as items. 我有一个带有ImageViews GridView片段。 The amount cells is around 25. 单元格的数量约为25。

For every Image I have a server request by Id. 对于每个图片,我都有ID的服务器请求。 So its 25 server requests. 因此,它有25个服务器请求。 Takes 2-3 seconds. 需要2-3秒。

How can I receive one image at a time and dynamically set it as content of cell? 如何一次接收一张图像并将其动态设置为单元格内容? And every cell, which doesn't have image yet should contain ProgressBar . 每个没有图像的单元格都应包含ProgressBar

What do I have now: I'm trying to load items in AsyncTask and return Bitmap array back to UI thread. 我现在拥有什么:我正在尝试在AsyncTask加载项目并将Bitmap数组返回到UI线程。 But I don't know how to do that for every Image. 但是我不知道如何为每个图像执行此操作。 My GridView appears only after ALL images downloaded. 仅在下载所有图像之后,我的GridView才会出现。 And it should be visible first with 25 elements which contain ProgressBars and no Images. 它应该首先可见,其中包含25个包含ProgressBars且没有图像的元素。


Code code 代码代号

fragment's onCreate() : 片段的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 : 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 adapter: 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;
}

Guys, I really need your help. 伙计们,我真的需要您的帮助。 Tell if some more code or explanations needed. 告诉是否需要更多代码或解释。

You can use publishProgress() for this to call onProgressUpdate() 您可以publishProgress()使用publishProgress()来调用onProgressUpdate()

So in your for loop something like 所以在你的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);
    }

then you will need to override onProgressUpdate() which is called by publishProgress() 那么你将需要重写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
    */
}

You then would need to change your asynctask to 然后,您需要将asynctask更改为

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

You also don't want to call .get() on your AsyncTask because it is a blocking call 您也不想在AsyncTask上调用.get() ,因为它是阻塞调用

Something similar to this should give you what you want. 与此类似的东西应该可以为您提供所需的东西。

Alternatives 备择方案

However, there are a lot of 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();
    }
}

and in the assynctask 并在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

    }

for progress bar I think what you are doing is correct change your adapter class's 对于进度条,我认为您的操作正确,请更改适配器类的

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

inside getView method 里面的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;
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM