从 AsyncTask 一次下载一个项目
Download one item at a time from AsyncTask
我有一个片段 GridView
和 ImageViews
作为项目。单元格数量约为 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;
}
}
我有一个片段 GridView
和 ImageViews
作为项目。单元格数量约为 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;
}
}