我正在尝试将缩略图形式的图片文件从内部存储加载到列表视图。目前,我正在使用ViewHolder,但滚动时加载仍然不稳定所以我将尝试使用AsyncTask。但是我无法理解如何构建AsyncTask,因为我发现大多数示例都是从网站下载的。我甚至不确定我是否应该在我的BaseAdapter或我的MainActivity中将其子类化。我在下面添加了我的baseadapter,底部是未完成的AsyncTask。我如何将其结构化为:使用AsyncTask来协助ViewHolder,或者直接将图像传递给AsyncTask并让它返回位图,以便ListView顺利滚动?
public class ListViewAdapter extends BaseAdapter {
private static final int WIDTH = 250;
private static final int HEIGHT = 250;
private static final int ROTATION = 90;
private final static String TAG = "Pictures";
private final ArrayList<SelfieObject> mItems = new ArrayList<SelfieObject>();
private Context mContext;
private File mStorageDir;
private String mFilePrefix;
public ListViewAdapter(Context context, File storageDir, String filePrefix) {
mContext = context;
mStorageDir = storageDir;
mFilePrefix = filePrefix;
//get file list from storage to display
InitializeItemsFromStorage(storageDir, filePrefix);
}
//this method creates an array of files stored on the device or SD card.
private void InitializeItemsFromStorage(File storageDir, String prefix) {
log("in InitializeItemsFromStorage()");
mItems.clear();
File[] files = getFiles(storageDir, prefix);
for (File f : files) {
SelfieObject selfie = new SelfieObject(f);
mItems.add(selfie);
}
}
public void Update() {
log("in Update()");
InitializeItemsFromStorage(mStorageDir, mFilePrefix);
notifyDataSetChanged();
}
/*
* return the list of file objects of the given directory that begin with
* the prefix.
*/
private File[] getFiles(File storageDir, final String prefix) {
FileFilter fileFilter = new FileFilter() {
@Override
public boolean accept(File pathname) {
if (pathname.isFile() && pathname.getName().startsWith(prefix))
return true;
else
return false;
}
};
File[] result = storageDir.listFiles(fileFilter);
return result;
}
public int getCount() {
log("in getCount()");
return mItems.size();
}
public Object getItem(int position) {
log("in getItem()");
return mItems.get(position);
}
public long getItemId(int position) {
log("in getItemId()");
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.v(TAG, "in getView for position " + position +
", convertView is " +
((convertView == null)?"null":"being recycled"));
View newView = convertView;
ViewHolder holder;
if (null == convertView) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
newView = inflater.inflate(R.layout.single_item, null);
holder = new ViewHolder();
holder.description = (TextView) newView.findViewById(R.id.textView1);
holder.picture = (ImageView) newView.findViewById(R.id.imageView1);
newView.setTag(holder);
} else {
holder = (ViewHolder) newView.getTag();
}
holder.picture.setScaleType(ImageView.ScaleType.CENTER_CROP);
SelfieObject selfie = (SelfieObject) getItem(position);
setPic(holder.picture, new Point(WIDTH, HEIGHT), selfie.getPath());
TextView textView = (TextView) holder.description;
textView.setText(selfie.getName());
log("Exiting getView");
return newView;
}
static class ViewHolder {
ImageView picture;
TextView description;
}
public void add(SelfieObject listItem) {
mItems.add(listItem);
notifyDataSetChanged();
}
public ArrayList<SelfieObject> getList(){
return mItems;
}
public void removeAllViews(){
mItems.clear();
this.notifyDataSetChanged();
}
public static void setPic(ImageView imageView, Point requestedSize,
String pathName) {
// set the dimensions of the View
int targetW = requestedSize.x;
int targetH = requestedSize.y;
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pathName, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = Math.min(photoW / targetW, photoH / targetH);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(pathName, bmOptions);
imageView.setImageBitmap(bitmap);
imageView.setRotation(ROTATION);
}
//Automation logging tool
public void log(String s){
Log.i(TAG, s);
}
private class AsyncTaskLoadImage extends AsyncTask<Object, Void, Bitmap>{
private ImageView image;
private String path;
public AsyncTaskLoadImage(ImageView image){
this.image = image;
this.path = image.getTag().toString();
}
@Override
protected Bitmap doInBackground(Object... params) {
Bitmap bitmap = null;
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + path);
if(file.exists()){
bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
}
return bitmap;
}
}
}
答案 0 :(得分:1)
AsyncTask应该做任何在UI线程中做得太慢的事情。在此示例中,应在后台完成对图像的提取和下采样以及设置ViewHolder。
但是,我建议您不要自己尝试修复ListView,而是查看现有的解决方案,例如:https://github.com/lucasr/smoothie
另外,我强烈建议你对你的位图进行下采样,否则会消耗大量的计算时间和内存。虽然前一个可以在滚动时滞后你的UI,但后者会给你一个很好的OutOfMemoryException。请参阅:http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html