我有这个CustomAdapter,用我的数据填充列表。问题是Imageview被下载并绘制了很多次。例如:
我在服务器上搜索视频列表:
(Video1) Title 1 Description 1
(Video2) Title 2 Description 2
(Video3) Title 3 Description 3
..
加载时,Video1中的图像加载,然后加载到同一Imageview,Video2Image加载,并再次加载列表中的每个视频,同样加载列表中的视频。当我滚动适配器时,再次下载所有图像。有一些方法可以解决这个问题,我不明白这种行为。
CustomAdapter.java
public class CustomAdapter extends ArrayAdapter<Video> {
// declaring our ArrayList of items
private ArrayList<Video> objects;
public CustomAdapter(Context context, int textViewResourceId, ArrayList<Video> objects) {
super(context, textViewResourceId, objects);
this.objects = objects;
}
public View getView(int position, View convertView, ViewGroup parent){
View v = convertView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.list_row, null);
}
Video i = objects.get(position);
if (i != null) {
TextView title = (TextView) v.findViewById(R.id.title);
TextView description = (TextView) v.findViewById(R.id.description);
ImageView imagen = (ImageView) v.findViewById(R.id.list_image);
title.setText(i.getTitulo());
description.setText(i.getDescripcion());
//Creamos imagen descargada y la seteamos
new DownloadImageTask(imagen).execute(i.getUrlimagen());
BitmapDrawable drawable = (BitmapDrawable) imagen.getDrawable();
Bitmap bitmap = drawable.getBitmap();
imagen.setImageBitmap(bitmap);
Log.i("Debug", "Creando una imagen para: " + i.getTitulo());
v.setTag(R.id.id_url, i.getUrl().trim());//1.Url
v.setTag(R.id.id_titulo,i.getTitulo().trim());//2.Título
v.setTag(R.id.id_video,i.getId().trim());//3.ID
}
return v;
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
BitmapFactory BitmapFactory = null;
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
if(result!=null)
bmImage.setImageBitmap(result);
}
}
public ArrayList getValues(){
return objects;
}
}
对不起我的英语。
答案 0 :(得分:1)
我有一段时间没遇到这个问题。如果您在getView()
中放入一个日志,只要您滚动到屏幕的末尾,就会看到它被调用。这意味着滚动时图像会被多次下载。
要解决此问题,您需要缓存位图。一旦有了缓存,每次调用getView时,都要先查询缓存FIRST以查看图像是否已经下载然后如果它不可用,请下载并将其添加到缓存中。
此方法在Android开发者处解释(带代码)。 http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
答案 1 :(得分:1)
我之前回答这个问题,然后我再次为你回答:不要重新发明轮子!
由于您现在看到的原因(以及其他内容管理,缓存管理等),图像下载/缓存非常复杂,所以只需使用一个有效的库。
以下是使用Picasso(我最喜欢的Android图像下载库)
的代码public View getView(int position, View convertView, ViewGroup parent){
View v = convertView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.list_row, null);
}
Video i = objects.get(position);
if (i != null) {
TextView title = (TextView) v.findViewById(R.id.title);
TextView description = (TextView) v.findViewById(R.id.description);
ImageView imagen = (ImageView) v.findViewById(R.id.list_image);
title.setText(i.getTitulo());
description.setText(i.getDescripcion());
//Creamos imagen descargada y la seteamos
Picasso
.with(imagen.getContext())
.load(i.getUrlimagen())
.into(imagen);
Log.i("Debug", "Creando una imagen para: " + i.getTitulo());
v.setTag(R.id.id_url, i.getUrl().trim());//1.Url
v.setTag(R.id.id_titulo,i.getTitulo().trim());//2.Título
v.setTag(R.id.id_video,i.getId().trim());//3.ID
}
return v;
}
完成!该代码负责线程,缓存,取消。
ps:你应该阅读更多的regaring适配器和ViewHolder模式,你没有正确地做到这一点。
答案 2 :(得分:0)
您的getview始终在创建DownloadImageTask。你不想这样做 - 你想检查一下你是否已经拥有它,并且只有在你没有的情况下才下载一个新的。