I am attempting to load picture files in the form of thumbnails from my internal storage to a list view. Currently, I am using a ViewHolder, but the loading is still choppy when scrolling so I am going to try to use an AsyncTask. However I can't get my head around how to structure the AsyncTask as most of the examples I've found deal with downloading from a website. I'm not even sure if I should subclass it in my BaseAdapter or in my MainActivity. I have added my baseadapter below with the unfinished AsyncTask at the bottom. How do I structure this to either: use the AsyncTask to assist the ViewHolder, or directly pass an image to AsyncTask and have it return the bitmap so the ListView will scroll smoothly?
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;
}
}
}