Reputation: 16978
I have a listview in which I'm loading all the images (as previews) from the user's SD card. I have a custom SimpleCursorAdapter and when I override the getView() method, I try to start background threads for the image loading.
What I'm trying to do is basically "lazy loading" the image previews into the listview using background threads or something. I'm open for new solutions. The main problem is that scrolling is ungodly slow since loading images is so expensive an operation.
Here's the relevant code I'm trying:
public class listOfImages extends SimpleCursorAdapter {
private Cursor c;
private Context context;
public listOfImages(Context context, int layout, Cursor c,
String[] from, int[] to) {
super(context, layout, c, from, to);
this.c = c;
this.context = context;
}
public View getView(int pos, View inView, ViewGroup parent) {
View v = inView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.image_item, null);
}
this.c.moveToPosition(pos);
int columnIndex = this.c.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME);
String name = this.c.getString(columnIndex);
columnIndex = this.c.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE);
String size = this.c.getString(columnIndex);
columnIndex = this.c.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
String data = this.c.getString(columnIndex); //gives the filename
TextView sTitle = (TextView) v.findViewById(R.id.image_title);
sTitle.setText(name);
imagePreviewLoader ipl = new imagePreviewLoader(v, data);
ipl.mainProcessing();
v.setTag(data);
v.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, "Image: " + v.getTag(), Toast.LENGTH_SHORT).show();
String filename = (String) v.getTag();
Intent intent = new Intent(context, ViewImage.class);
intent.putExtra("filename", filename);
context.startActivity(intent);
}
});
return v;
}
}
And now the background threading that I'm trying:
public class imagePreviewLoader {
private Handler handler = new Handler();
private View v;
private String data;
public imagePreviewLoader(View v, String data) {
this.v = v;
this.data = data;
}
protected void mainProcessing() {
Thread thread = new Thread(null, doBackground, "Background");
thread.start();
}
private Runnable doBackground = new Runnable() {
public void run() {
backgroundThreadProcessing();
}
};
private void backgroundThreadProcessing() {
handler.post(doUpdateGUI);
}
private Runnable doUpdateGUI = new Runnable() {
public void run() {
updateGUI();
}
};
private void updateGUI() {
ImageView img = (ImageView) v.findViewById(R.id.image_view);
BitmapFactory.Options bfo = new BitmapFactory.Options();
bfo.inSampleSize = 30;
bfo.inTargetDensity = 50;
Bitmap bm = BitmapFactory.decodeFile(data, bfo);
img.setImageBitmap(bm);
}
}
The issue is that everything tries to load at once when you scroll, so scrolling is really slow. I thought what would happen is the imageview would just stay blank (or a placeholder) until the thread has loaded the appropriate image. I guess not though.
Thanks for any help.
Upvotes: 1
Views: 5909
Reputation: 116
I have an easy to use library under a basically public domain license that you can check out... It will cancel loading for rows that aren't displaying and uses two threads to do image loading.
You can check it out on my GitHub: https://github.com/tbiehn/Android-Adapter-Image-Loader
Upvotes: 1