图像缩略图设置不正确
Posted
技术标签:
【中文标题】图像缩略图设置不正确【英文标题】:Image thumbnails not setting correctly 【发布时间】:2017-10-28 05:14:56 【问题描述】:我正在尝试制作一个文件浏览器。我实现了这一切,只是我的图像缩略图加载太慢了。所以我读到我必须转移到 asynctask,然后在执行后更新 ui。在运行 asynctask 之前,我为所有文件提供了默认缩略图。在 asynctask 中,我将位置作为参数,因为我使用它们设置标签。然后我使用该位置检查文件。如果那是图像或视频,我会为它创建一个位图。在后期执行中,我创建了一个新的查看器并使用 getTag(position) 为其分配相同的标签。然后我使用 setBitmapImage 分配位图。问题:即使不是图像/视频的文件,缩略图也会发生变化/闪烁。 到目前为止我尝试过的事情: a)updating of Image Thumbnails using AsyncTask for android ListView not coming proper b)Android ListView updating of Image Thumbnails using AsyncTask Causes View recycling
这是我的 getView 代码:
@Override
public View getView(final int position, View convertView, ViewGroup parent)
File file=new File(String.valueOf(filenames[position]));
if(file.isDirectory())
img=R.drawable.folder;
else
img=getImage(filenames[position]);
ViewHolder viewHolder = null;
if (convertView == null)
LayoutInflater inflator = LayoutInflater.from(getContext());
convertView = inflator.inflate(R.layout.list_item, null);
viewHolder = new ViewHolder();
viewHolder.tv = (TextView) convertView.findViewById(R.id.textView1);
viewHolder.cb = (CheckBox) convertView.findViewById(R.id.checkBox1);
viewHolder.iv= (ImageView)convertView.findViewById(R.id.imageView);
viewHolder.cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
int getPosition = (Integer) buttonView.getTag(); // Here we get the position that we have set for the checkbox using setTag.
myList.get(getPosition).setSelected(buttonView.isChecked()); // Set the value of checkbox to maintain its state.
);
convertView.setTag(viewHolder);
convertView.setTag(R.id.textView1, viewHolder.tv);
convertView.setTag(R.id.checkBox1, viewHolder.cb);
convertView.setTag(R.id.checkBox1, viewHolder.iv);
else
viewHolder = (ViewHolder) convertView.getTag();
viewHolder.iv.getLayoutParams().height = 80;
viewHolder.iv.getLayoutParams().width = 80;
viewHolder.cb.setTag(position);
final ViewHolder ViewHolder= viewHolder;
ViewHolder.iv.setImageResource(img);
ViewHolder.tv.setText(myList.get(position).getName());
ViewHolder.cb.setChecked(myList.get(position).isSelected());
final View finalConvertView = convertView;
class myTask extends AsyncTask<Integer,Void,Bitmap>
int pos;
public myTask(int pos)
this.pos=pos;
@Override
protected Bitmap doInBackground(Integer... params)
Bitmap thumb=null;
if((String.valueOf(filenames[pos])).contains(".jpeg")||String.valueOf(filenames[pos]).contains(".jpg")||String.valueOf(filenames[pos]).contains(".png")||String.valueOf(filenames[pos]).contains(".bmp")||String.valueOf(filenames[pos]).contains(".webp")||String.valueOf(filenames[pos]).contains(".gif"))
thumb = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(String.valueOf(filenames[pos])), 64, 64);
else if((String.valueOf(filenames[pos])).contains(".mp4")||String.valueOf(filenames[pos]).contains(".mkv")||String.valueOf(filenames[pos]).contains(".webm")||String.valueOf(filenames[pos]).contains(".3gp")||String.valueOf(filenames[pos]).contains(".3gpp"))
thumb=ThumbnailUtils.createVideoThumbnail(filenames[pos].getPath(), MediaStore.Video.Thumbnails.MINI_KIND);
return thumb;
@Override
protected void onPostExecute(Bitmap thumb)
if(isCancelled())
return;
ViewHolder v= (ViewHolder) finalConvertView.getTag(pos);
if((String.valueOf(filenames[pos])).contains(".jpeg")||String.valueOf(filenames[pos]).contains(".jpg")||String.valueOf(filenames[pos]).contains(".png")||String.valueOf(filenames[pos]).contains(".bmp")||String.valueOf(filenames[pos]).contains(".webp")||String.valueOf(filenames[pos]).contains(".gif"))
v.iv.setImageBitmap(thumb);
else if((String.valueOf(filenames[pos])).contains(".mp4")||String.valueOf(filenames[pos]).contains(".mkv")||String.valueOf(filenames[pos]).contains(".webm")||String.valueOf(filenames[pos]).contains(".3gp")||String.valueOf(filenames[pos]).contains(".3gpp"))
v.iv.setImageBitmap(thumb);
myTask m=new myTask(position);
m.execute();
return convertView;
【问题讨论】:
【参考方案1】:我终于找到了答案。
这是 ListAdapter 类:
class ListAdapter extends ArrayAdapter<Modal>
private final Context context;
private int img;
private List<Modal> myList;
private File filenames[];
private List<Integer> selectedItems=new ArrayList<Integer>();
private CheckBox cb;
public ListAdapter(Context context, List<Modal> list, File filenames[])
super(context, R.layout.list_item, list);
this.context = context;
this.myList = list;
this.filenames=filenames;
@Override
public int getViewTypeCount()
if(getCount()>0)
return getCount();
return 1;
@Override
public int getItemViewType(int position)
return position;
@Override
public long getItemId(int position)
return position;
static class ViewHolder
TextView tv;
CheckBox cb;
static ImageView iv;
public int getImage(File filename)
if(String.valueOf(filename).contains(".rar")||String.valueOf(filename).contains(".zip"))
return R.drawable.archive;
else if(String.valueOf(filename).contains(".doc")||String.valueOf(filename).contains(".docx"))
return R.drawable.doc;
else if(String.valueOf(filename).contains(".pdf"))
return R.drawable.pdf;
else if(String.valueOf(filename).contains(".txt"))
return R.drawable.txt;
else if(String.valueOf(filename).contains(".ppt")||String.valueOf(filename).contains(".pptx"))
return R.drawable.ppt;
else if(String.valueOf(filename).contains(".xls")||String.valueOf(filename).contains(".xlsx"))
return R.drawable.xls;
else if((String.valueOf(filename).contains(".jpeg")||String.valueOf(filename).contains(".jpg")||String.valueOf(filename).contains(".png")||String.valueOf(filename).contains(".bmp")||String.valueOf(filename).contains(".webp")||String.valueOf(filename).contains(".gif")))
return R.drawable.image;
else if((String.valueOf(filename).contains(".mp4")||String.valueOf(filename).contains(".mkv")||String.valueOf(filename).contains(".webm")||String.valueOf(filename).contains(".3gp")||String.valueOf(filename).contains(".3gpp"))||String.valueOf(filename).contains(".MOV"))
return R.drawable.video;
else if((String.valueOf(filename).contains(".mp3")||String.valueOf(filename).contains(".wav")||String.valueOf(filename).contains(".wma")||String.valueOf(filename).contains(".MP2")||String.valueOf(filename).contains(".AAC")||String.valueOf(filename).contains(".AC3")||String.valueOf(filename).contains(".AU")||String.valueOf(filename).contains(".OGG")||String.valueOf(filename).contains(".FLAC")))
return R.drawable.music;
else
return R.drawable.unknown;
@Override
public View getView(final int position, View convertView, ViewGroup parent)
File file=new File(String.valueOf(filenames[position]));
if(file.isDirectory())
img=R.drawable.folder;
else
img=getImage(filenames[position]);
ViewHolder viewHolder = null;
if (convertView == null)
LayoutInflater inflator = LayoutInflater.from(getContext());
convertView = inflator.inflate(R.layout.list_item, null);
viewHolder = new ViewHolder();
viewHolder.tv = (TextView) convertView.findViewById(R.id.textView1);
viewHolder.cb = (CheckBox) convertView.findViewById(R.id.checkBox1);
viewHolder.iv= (ImageView)convertView.findViewById(imageView);
viewHolder.cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
int getPosition = (Integer) buttonView.getTag(); // Here we get the position that we have set for the checkbox using setTag.
myList.get(getPosition).setSelected(buttonView.isChecked()); // Set the value of checkbox to maintain its state.
);
convertView.setTag(viewHolder);
convertView.setTag(R.id.textView1, viewHolder.tv);
convertView.setTag(R.id.checkBox1, viewHolder.cb);
convertView.setTag(R.id.checkBox1, viewHolder.iv);
else
viewHolder = (ViewHolder) convertView.getTag();
viewHolder.iv.getLayoutParams().height = 150;
viewHolder.iv.getLayoutParams().width = 150;
viewHolder.cb.setTag(position);
final ViewHolder ViewHolder= viewHolder;
ViewHolder.tv.setText(myList.get(position).getName());
ViewHolder.cb.setChecked(myList.get(position).isSelected());
viewHolder.iv.setImageResource(img);
Log.v("this","viewHolderMT: "+String.valueOf(viewHolder)+" position: "+position);
myTask m=new myTask(position,viewHolder.iv);
m.execute();
return convertView;
class myTask extends AsyncTask<Integer,Bitmap,Bitmap>
int pos;
ImageView iv;
public myTask(int pos,ImageView iv)
this.pos=pos;
this.iv=iv;
iv.setTag(pos);
@Override
protected Bitmap doInBackground(Integer... params)
Bitmap thumb=null;
if((String.valueOf(filenames[pos])).contains(".jpeg")||String.valueOf(filenames[pos]).contains(".jpg")||String.valueOf(filenames[pos]).contains(".png")||String.valueOf(filenames[pos]).contains(".bmp")||String.valueOf(filenames[pos]).contains(".webp")||String.valueOf(filenames[pos]).contains(".gif"))
thumb = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(String.valueOf(filenames[pos])), 150, 150);
else if((String.valueOf(filenames[pos])).contains(".mp4")||String.valueOf(filenames[pos]).contains(".mkv")||String.valueOf(filenames[pos]).contains(".webm")||String.valueOf(filenames[pos]).contains(".3gp")||String.valueOf(filenames[pos]).contains(".3gpp")||String.valueOf(filenames[pos]).contains(".MOV"))
thumb=ThumbnailUtils.createVideoThumbnail(filenames[pos].getPath(), MediaStore.Video.Thumbnails.MINI_KIND);
return thumb;
@Override
protected void onProgressUpdate(Bitmap... thumb)
@Override
protected void onPostExecute(Bitmap thumb)
if(thumb!=null && (Integer)iv.getTag()==this.pos)
if ((String.valueOf(filenames[pos])).contains(".jpeg") || String.valueOf(filenames[pos]).contains(".jpg") || String.valueOf(filenames[pos]).contains(".png") || String.valueOf(filenames[pos]).contains(".bmp") || String.valueOf(filenames[pos]).contains(".webp") || String.valueOf(filenames[pos]).contains(".gif"))
iv.setImageBitmap(thumb);
else if ((String.valueOf(filenames[pos])).contains(".mp4") ||String.valueOf(filenames[pos]).contains(".MOV")|| String.valueOf(filenames[pos]).contains(".mkv") || String.valueOf(filenames[pos]).contains(".webm") || String.valueOf(filenames[pos]).contains(".3gp") || String.valueOf(filenames[pos]).contains(".3gpp"))
iv.setImageBitmap(thumb);
我犯的错误:
将 AsyncTask 移到 getview() 之外 在异步构造函数中提供对 imageView 的引用 同时实现 getItemViewType() 和 getItemId() 函数 未检查 onPostExecute 中的位置标记,因此图像正在随机播放。我花了一段时间才弄清楚。希望对其他人有所帮助!
【讨论】:
欢迎任何关于效率或其他方面的建议。以上是关于图像缩略图设置不正确的主要内容,如果未能解决你的问题,请参考以下文章
PHP 缩略图图像生成器缓存:如何在 PHP 中正确设置 If-Last-Modified/Max-Age/Last-Modified HEADERS?