我有一个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;
}
伙计们,我真的需要你的帮助。 告诉您是否需要更多代码或解释。
答案 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
}
@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;
}
}