Android ListView使用AsyncTask更新图像缩略图会导致视图回收
我一直在尝试让缩略图处理ListView中图像文件的异步任务。 我遇到了行循环的常见问题,因此在滚动时,缩略图被分配到错误的行。我曾尝试向ImageView添加标记,然后在AsyncTask中确认onPostExecute()中的标记,但都没有成功。有人请帮忙 自定义适配器如下所示:Android ListView使用AsyncTask更新图像缩略图会导致视图回收,android,listview,android-asynctask,thumbnails,recycle,Android,Listview,Android Asynctask,Thumbnails,Recycle,我一直在尝试让缩略图处理ListView中图像文件的异步任务。 我遇到了行循环的常见问题,因此在滚动时,缩略图被分配到错误的行。我曾尝试向ImageView添加标记,然后在AsyncTask中确认onPostExecute()中的标记,但都没有成功。有人请帮忙 自定义适配器如下所示: public class MySimpleAdapter extends SimpleAdapter { public MySimpleAdapter(Context context,
public class MySimpleAdapter extends SimpleAdapter {
public MySimpleAdapter(Context context,
List<? extends Map<String, ?>> data, int resource,
String[] from, int[] to) {
super(context, data, resource, from, to);
// TODO Auto-generated constructor stub
}
public View getView(int position, View convertView, ViewGroup parent) {
final View v = super.getView(position, convertView, parent);
thumbnail = (ImageView) v.findViewById(R.id.thumbnail);
checker = (CheckBox) v.findViewById(R.id.checkBox);
filenametext = (TextView) v.findViewById(R.id.text1);
String pathtoimage = startLocation.concat("/"
+ filenametext.getText().toString());
desctext = (TextView) v.findViewById(R.id.text2);
String temp = desctext.getText().toString();
if (temp.equals("Directory") == true) {
checker.setEnabled(false);
switch (theme) {
case 0:
thumbnail.setImageResource(R.drawable.folder_light);
break;
case 1:
thumbnail.setImageResource(R.drawable.folder_dark);
break;
}
} else {
checker.setEnabled(true);
if (filenametext.getText().toString().endsWith(".jpg")
|| filenametext.getText().toString().endsWith(".png")
|| filenametext.getText().toString().endsWith(".bmp")) {
Boolean hashmapfound = false;
for (HashMap.Entry<String, Bitmap> entry : thumbnaillist
.entrySet()) {
String key = entry.getKey();
if (key.equals(filenametext.getText().toString())) {
Log.d(TAG, "HashMapKey Found!");
thumbnail.setImageBitmap(entry.getValue());
hashmapfound = true;
}
}
if (!hashmapfound) {
Log.d(TAG, "NO HashMapKey Found! Adding to HashMap!");
switch (theme) {
case 0:
thumbnail
.setImageResource(R.drawable.unknown_image_light);
break;
case 1:
thumbnail
.setImageResource(R.drawable.unknown_image_dark);
break;
}
thumbnail.setTag((filenametext.getText().toString()));
new GetBitMaps(thumbnail).execute(pathtoimage,
filenametext.getText().toString());
}
} else {
switch (theme) {
case 0:
thumbnail.setImageResource(R.drawable.file_light);
break;
case 1:
thumbnail.setImageResource(R.drawable.file_dark);
break;
}
}
}
return v;
}
}
公共类mysimpledapter扩展了simpledapter{
公共MySimpleAdapter(上下文,
列表>数据,int资源,
字符串[]从,整数[]到){
超级(上下文、数据、资源、从、到);
//TODO自动生成的构造函数存根
}
公共视图getView(int位置、视图转换视图、视图组父视图){
最终视图v=super.getView(位置、转换视图、父视图);
缩略图=(ImageView)v.findViewById(R.id.缩略图);
checker=(复选框)v.findviewbyd(R.id.CheckBox);
filenametext=(TextView)v.findviewbyd(R.id.text1);
字符串pathtoimage=startLocation.concat(“/”)
+filenametext.getText().toString());
desctext=(TextView)v.findViewById(R.id.text2);
字符串temp=desctext.getText().toString();
if(临时等于(“目录”)==true){
checker.setEnabled(false);
切换(主题){
案例0:
缩略图.setImageResource(R.drawable.folder_light);
打破
案例1:
缩略图.setImageResource(R.drawable.folder_深色);
打破
}
}否则{
checker.setEnabled(true);
if(filenametext.getText().toString().endsWith(“.jpg”)
||filenametext.getText().toString().endsWith(“.png”)
||filenametext.getText().toString().endsWith(“.bmp”)){
布尔hashmapfound=false;
对于(HashMap.Entry:thumbnaillist
.entrySet()){
String key=entry.getKey();
if(key.equals(filenametext.getText().toString())){
Log.d(标记“HashMapKey已找到!”);
setImageBitmap(entry.getValue());
hashmapfound=true;
}
}
如果(!hashmapfound){
d(标记“未找到HashMapKey!添加到HashMap!”);
切换(主题){
案例0:
缩略图
.setImageResource(R.drawable.unknown_image_light);
打破
案例1:
缩略图
.setImageResource(R.drawable.unknown_image_dark);
打破
}
setTag((filenametext.getText().toString());
新建GetBitmap(缩略图)。执行(pathtoimage,
filenametext.getText().toString());
}
}否则{
切换(主题){
案例0:
setImageResource(R.drawable.file_light);
打破
案例1:
setImageResource(R.drawable.file_暗);
打破
}
}
}
返回v;
}
}
异步任务如下所示:
class GetBitMaps extends AsyncTask<String, Void, Bitmap> {
private ImageView thumbnail;
private String imageName;
public GetBitMaps(ImageView thumb) {
// TODO Auto-generated constructor stub
thumbnail = thumb;
}
@Override
protected Bitmap doInBackground(String... pathtoimage) {
Bitmap bmp = createThumbnail(pathtoimage[0]);
thumbnaillist.put(pathtoimage[1], bmp);
imageName = pathtoimage[1];
return bmp;
}
@Override
protected void onPostExecute(Bitmap bmp) {
if (((String) thumbnail.getTag()).equals(imageName)) {
thumbnail.setImageBitmap(bmp);
}
}
private Bitmap createThumbnail(String filepath) {
Bitmap bmp = BitmapFactory.decodeFile(filepath);
int w = bmp.getWidth();
int h = bmp.getHeight();
if (w > h) {
w = 80;
h = 40;
} else if (w < h) {
w = 40;
h = 80;
}
bmp = Bitmap.createScaledBitmap(bmp, w, h, true);
return bmp;
}
}
class GetBitMaps扩展了异步任务{
私有图像视图缩略图;
私有字符串imageName;
公共获取位图(ImageView){
//TODO自动生成的构造函数存根
缩略图=拇指;
}
@凌驾
受保护位图doInBackground(字符串…路径图像){
位图bmp=创建缩略图(路径图像[0]);
thumbnaillist.put(pathtoimage[1],bmp);
imageName=pathtoimage[1];
返回bmp;
}
@凌驾
受保护的void onPostExecute(位图bmp){
if(((字符串)thumbnail.getTag()).equals(imageName)){
设置图像位图(bmp);
}
}
私有位图创建缩略图(字符串文件路径){
位图bmp=BitmapFactory.decodeFile(文件路径);
int w=bmp.getWidth();
int h=bmp.getHeight();
如果(w>h){
w=80;
h=40;
}否则如果(w
我仍然不知道还需要做什么才能在滚动时让缩略图显示在正确的行上
请注意:在离开受影响的行并向下滚动后,一切正常,但滚动问题不会消失 来自:
您要做的是在一个单独的线程中异步运行所有每行IO或任何重载CPU绑定例程。这里的诀窍是这样做,并且仍然遵守ListView的回收行为。例如,如果运行AsyncTask在适配器的getView()中加载配置文件图片,则在AsyncTask完成之前,加载映像的视图可能会被循环到另一个位置。因此,您需要一种机制来知道在完成异步操作后视图是否还没有被回收
实现这一点的一个简单方法是将一些信息附加到视图中,以标识与其关联的行。然后,您可以检查在异步操作时视图的目标行是否仍然相同
public View getView(int position, View convertView,
ViewGroup parent) {
ViewHolder holder;
...
holder.position = position;
new ThumbnailTask(position, holder)
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null);
return convertView;
}
private static class ThumbnailTask extends AsyncTask {
private int mPosition;
private ViewHolder mHolder;
public ThumbnailTask(int position, ViewHolder holder) {
mPosition = position;
mHolder = holder;
}
@Override
protected Cursor doInBackground(Void... arg0) {
// Download bitmap here
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (mHolder.position == mPosition) {
mHolder.thumbnail.setImageBitmap(bitmap);
}
}
}
private static class ViewHolder {
public ImageView thumbnail;
public int position;
}