【发布时间】:2015-07-09 05:40:13
【问题描述】:
我在尝试管理 AsyncTask 类中的位图时遇到问题。
我认为我的一切设置都很好,但是当我尝试显示代码在循环中执行的图像时会发生什么,并且相同的图像视图最终会出现故障,一次在同一图像中设置许多不同的图像(它是很难解释)。我正在通过适配器中的 getView 方法执行 AsyncTask。
这是我的 ListView 适配器类,也许有人可以弄清楚它有什么问题:
public class SongsAdapterNew extends ArrayAdapter<String> {
ArrayList<String> names;
ArrayList<String> images;
Activity context;
ImageView imageView;
static class ViewHolder {
private TextView text;
private ImageView image;
}
public SongsAdapterNew(Activity context, ArrayList<String> names,
ArrayList<String> images) {
super(context, R.layout.songs_row, names);
this.names = names;
this.context = context;
this.images = images;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder mViewHolder = null;
if (convertView == null) {
mViewHolder = new ViewHolder();
LayoutInflater vi = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.songs_row, parent, false);
mViewHolder.text = (TextView) convertView
.findViewById(R.id.songTextView);
imageView = mViewHolder.image = (ImageView) convertView
.findViewById(R.id.imageView1);
convertView.setTag(mViewHolder);
}
else {
mViewHolder = (ViewHolder) convertView.getTag();
}
mViewHolder.text.setText(names.get(position));
new ImageLoader().execute(mViewHolder.image, images.get(position));
return convertView;
}
public class ImageLoader extends AsyncTask<Object, String, Bitmap> {
private View view;
private Bitmap bitmap = null;
MediaMetadataRetriever mmr;
byte[] rawArt = null;
Bitmap art1;
BitmapFactory.Options bfo;
@Override
protected Bitmap doInBackground(Object... parameters) {
// Get the passed arguments here
view = (View) parameters[0];
String uri = (String) parameters[1];
mmr = new MediaMetadataRetriever();
bfo = new BitmapFactory.Options();
bfo.inSampleSize = 5;
try {
mmr.setDataSource(uri);
rawArt = mmr.getEmbeddedPicture();
bitmap = BitmapFactory.decodeByteArray(rawArt, 0,
rawArt.length, bfo);
} catch (Exception e) {
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
}
else {
imageView.setImageResource(R.drawable.songs);
}
}
}
}
【问题讨论】:
-
您没有考虑行回收。随着用户滚动,行被回收,您开始新任务以加载新图像......但旧任务仍然未完成。另外,使用
execute(),旧任务将在新任务开始之前运行完成。一般来说,这个问题已经被许多图像加载库(例如 Picasso、Universal Image Loader)解决了。哪些支持您的特定数据源,我不能说,尽管有些应该有可插入的方式来规定要加载的图像。 -
那些图像加载库不支持我的数据源,我传递 AsyncTask 的字符串是用户设备上特定歌曲的直接路径,而不是艺术。
-
“那些图像加载库不支持我的数据源”——是的,但您可以插入自己的数据源。在 Universal Image Loader 的情况下,制作你自己的方案(例如,
media.metadata://),扩展BaseImageDownloader,覆盖getStreamFromOtherSource(),把你的MediaMetadataRetriever逻辑放在那里,然后通过imageDownloader()在@987654328上注册你的下载器@。然后,以您的方案开头的路径将路由到您的getStreamFromOtherSource(),而 UIL 将处理所有异步内容、缓存、行回收等。 -
CommonsWare 所说的。尤其是第一句话。如果您不想使用库(但我不明白为什么不应该使用),请在回收视图时取消图像。
-
@Christine 如果可以的话,我很想使用图像加载库,但我不会从 URLS 加载图像。我会尝试尝试 CommonsWare 的解决方案。
标签: android android-listview android-adapter