GridView从URL加载图片。当我滚动gridview,更多的图像机会,如何解决它...我尝试过imageAdapter.notifyDataSetChanged(),gridView.invalidateViews()..我还没有找到解决这个问题的方法。
public class ImageAdapter extends BaseAdapter{
private Context mContext;
private LayoutInflater mInflater;
private ArrayList<NodeFood> listImage = new ArrayList<NodeFood>();
public ImageAdapter(Context c, ArrayList<NodeFood> listImage){
this.mContext = c;
this.listImage = listImage;
}
public class ViewHolder{
ImageView imageView;
ProgressBar progress;
}
public int getCount() {
return listImage.size();
}
public Object getItem(int arg0) {
return arg0;
}
public long getItemId(int arg0) {
return arg0;
}
public View getView(int arg0, View arg1, ViewGroup arg2) {
final ViewHolder holder;
if(arg1 == null){
holder = new ViewHolder();
mInflater = LayoutInflater.from(mContext);
arg1 = mInflater.inflate(R.layout.layout_item_grid, null);
holder.imageView = (ImageView)arg1.findViewById(R.id.imageItemGrid);
holder.progress = (ProgressBar)arg1.findViewById(R.id.progressBar);
holder.progress.getIndeterminateDrawable().setColorFilter(0xFFFF0000,android.graphics.PorterDuff.Mode.MULTIPLY);
arg1.setTag(holder);
}else{
holder = (ViewHolder)arg1.getTag();
}
holder.imageView.setTag(arg0);
holder.progress.setTag(arg0);
NodeFood a = this.listImage.get(arg0);
String URL = a.getSRC();
task_LoadIMG bb = new task_LoadIMG(URL,holder);
bb.execute();
return arg1;
}
public class task_LoadIMG extends AsyncTask<Void,Void,Bitmap>{
private String url;
private ViewHolder holder;
public task_LoadIMG(String url, ViewHolder holder){
this.url = url;
this.holder = holder;
}
@Override
protected Bitmap doInBackground(Void... arg0) {
try{
URL aURL = new URL(this.url);
URLConnection connect = aURL.openConnection();
connect.connect();
InputStream is = connect.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
Bitmap bm = BitmapFactory.decodeStream(bis);
bis.close();
is.close();
return bm;
}catch(IOException e){
return null;
}
}
@Override
protected void onPostExecute(Bitmap result) {
holder.progress.setVisibility(View.GONE);
holder.imageView.setImageBitmap(result);
holder.imageView.setScaleType(ScaleType.CENTER_CROP);
}
}
}
答案 0 :(得分:3)
问题是您的AsyncTask
加载图片的时间比显示的图片要长。一旦完成下载,该单元格已经过去了,并且已经被回收用于下一张图像。
要解决此问题,请将单元格图像的URL存储在单元格的tag
属性中。然后,检查以确保AsyncTask
完成时单元格URL相同。如果它不相同,那么单元格在此期间已被回收,您应该放弃更新。这是一些代码:
public View getView(int arg0, View arg1, ViewGroup arg2) {
final ViewHolder holder;
if(arg1 == null){
holder = new ViewHolder();
mInflater = LayoutInflater.from(mContext);
arg1 = mInflater.inflate(R.layout.layout_item_grid, null);
holder.imageView = (ImageView)arg1.findViewById(R.id.imageItemGrid);
holder.progress = (ProgressBar)arg1.findViewById(R.id.progressBar);
holder.progress.getIndeterminateDrawable().setColorFilter(0xFFFF0000,android.graphics.PorterDuff.Mode.MULTIPLY);
arg1.setTag(holder);
}else{
holder = (ViewHolder)arg1.getTag();
}
NodeFood a = this.listImage.get(arg0);
String URL = a.getSRC();
holder.imageView.setTag(URL);
task_LoadIMG bb = new task_LoadIMG(URL,holder);
bb.execute();
return arg1;
}
public class task_LoadIMG extends AsyncTask<Void,Void,Bitmap>{
private String url;
private ViewHolder holder;
public task_LoadIMG(String url, ViewHolder holder){
this.url = url;
this.holder = holder;
}
@Override
protected Bitmap doInBackground(Void... arg0) {
try{
URL aURL = new URL(this.url);
URLConnection connect = aURL.openConnection();
connect.connect();
InputStream is = connect.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
Bitmap bm = BitmapFactory.decodeStream(bis);
bis.close();
is.close();
return bm;
}catch(IOException e){
return null;
}
}
@Override
protected void onPostExecute(Bitmap result) {
if (url.equals(holder.imageView.getTag()) {
holder.progress.setVisibility(View.GONE);
holder.imageView.setImageBitmap(result);
holder.imageView.setScaleType(ScaleType.CENTER_CROP);
} else {
// View was updated in the meantime, ignore the image
}
}
}
您可能还会考虑在单元格被回收后立即取消AsyncTask
以节省带宽/ CPU周期。这是留给读者的练习。
答案 1 :(得分:0)
我使用排球,你可以摆脱所有异步任务,标签......
使用com.android.volley.toolbox.NetworkImageView重新使用ImageView
类似的东西:
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/twitter_avatar"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
android:layout_marginRight="6dip"/>
private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;
private LruCache<String, Bitmap> mMemoryCache;
然后:
final int memClass = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
// Use 1/8th of the available memory for this memory cache.
final int cacheSize = 1024 * 1024 * memClass / 8;
mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
protected int sizeOf(String key, Bitmap bitmap) {
// The cache size will be measured in bytes rather than number of items.
return bitmap.getByteCount();
}
};
mRequestQueue = Volley.newRequestQueue(context);
mImageLoader = new ImageLoader(mRequestQueue, new ImageLoader.ImageCache() {
public void putBitmap(String url, Bitmap bitmap) {
mMemoryCache.put(url, bitmap);
}
public Bitmap getBitmap(String url) {
return mMemoryCache.get(url);
}
});
使用Volley:
NetworkImageView image = (NetworkImageView) row.findViewById(R.id.ivGridViewImage);
image.setImageUrl(url, mImageLoader);
答案 2 :(得分:0)
我的GridView
遇到了同样的问题。虽然没有多少项目,只有24,我从手机的SD卡而不是在线加载图像,当我滚动时,我仍然得到图像四处跳跃,这实际上只是一两行被隐藏从一次来看。
我所做的只是添加一个ViewHolder
并修复了。看起来这个tutorial与@ scompt.com类似地实现它。他在本教程中的观点是,对于这样的ViewHolder
,当视图被回收时,不会重复调用findViewById()
。这可能就是为什么图像在滚动时不再跳转的原因。
不确定这是否会帮助处于同样困境的其他人。我搜索了S.O.对于这个问题,很少有人解决它。希望它可以帮到某人。
在我的适配器类中: PhotoGridItem
是我的模型类,在我的ArrayAdapter
扩展名中输入,如下所示:ArrayAdapter<PhotoGridItem>
。只是为了解释我的代码。
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
final ViewHolder holder;
if (row == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(resourceId, parent, false);
holder = new ViewHolder();
holder.imageView = (ImageView) row.findViewById(R.id.photo_grid_view);
// stores holder with view
row.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
PhotoGridItem photoGridItem = getItem(position);
if (photoGridItem != null) {
bm = photoGridItem.getImage();
holder.imageView.setImageBitmap(bm);
// positioning the image in the GridView slot
holder.imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
holder.imageView.setLayoutParams(new LinearLayout.LayoutParams
(270, 270));
}
return row;
}
public class ViewHolder{
ImageView imageView;
}