Hi all,
I have searched a lot for my problem, I found a lot of posts with similar problems, but no one gave me a correct solution.
What I want is a gridview displaying a sdcard folder's images. I also have to offer the possibility to take a picture, and when going back to the gridview, update it with the new picture.
To take the picture, I use this code :
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, getImageFileUri());
startActivityForResult(intent, TAKE_PICTURE_ACTIVITY);
Where getImageFileUri() is a function giving me a picture name with a timestamp, using Environment.getExternalStorageDirectory() to get the sdcard path, and checking if the folder exists (and create it if it doesn't).
For the moment, I use a cursor to get my images :
private void displayGallery() {
// Query params :
Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.Images.Media._ID};
String selection = MediaStore.Images.Media.DATA + " like ? ";
String[] selectionArgs = {"%Otiama%"};
// Submit the query :
mCursor = managedQuery(uri, projection, selection, selectionArgs, null);
if (mCursor != null) {
mGridView.setOnItemClickListener(this);
mGridView.setAdapter(new ImageAdapter(this, mCursor));
}
else showToast("Gallery is empty : " + uri.toString());
}
And here is my adapter's getView :
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = new ImageView(mContext);
// Move cursor to current position
mCursor.moveToPosition(position);
// Get the current value for the requested column
int columnIndex = mCursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID);
int imageID = mCursor.getInt(columnIndex);
// obtain the image URI
Uri uri = Uri.withAppendedPath( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, Integer.toString(imageID) );
String url = uri.toString();
// Set the content of the image based on the image URI
int originalImageId = Integer.parseInt(url.substring(url.lastIndexOf("/") + 1, url.length()));
Bitmap b = MediaStore.Images.Thumbnails.getThumbnail(mContext.getContentResolver(), originalImageId, MediaStore.Images.Thumbnails.MINI_KIND, null);
imageView.setImageBitmap(b);
return imageView;
}
This code works, but is very slow and doesn't update (new pictures's thumbnails aren't created), even if I call again my displayGallery() function in the onActivityResult(). Well, it doesn't update even if I reload the app >< . I have to run it again from eclipse.
In fact, what I would like is the same behavior than ES File Explorer (when you open a folder, the pictures have all a preview image, and they are loaded asynchronously), which, I think, doesn't use those ** thumbnails.
So I tried to load the pictures as bitmaps using the bitmap factory, but even with a few pictures (1-2), I instantly get a "java.lang.OutOfMemoryError: bitmap size exceeds VM budget"... I guess I have to resize them, but if I do so, won't I have the same error when I will load 20-30 pictures ?? Or the problem is that each picture exceeds the budget, and so if I resize them I will avoid this error for all of them ?
Sorry for the big post, if someone can help...
Well, I answer myself :
I created my own thumbnails this way :
public static Bitmap resizedBitmap(Bitmap bitmap, int newWidth) {
// Get the bitmap size :
int width = bitmap.getWidth();
int height = bitmap.getHeight();
double ratio = (double)width / (double)height;
// Compute the thumbnail size :
int thumbnailHeight = newWidth;
int thumbnailWidth = (int) ( (double)thumbnailHeight * ratio);
// Create a scaled bitmap :
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, thumbnailWidth, thumbnailHeight, false);
return scaledBitmap;
}
I don't use cursors anymore, to load the thumbnails I proceed like this (in the ImageAdapter) :
public void loadThumbnails() {
// Init the ArrayList :
_thumbnails = new ArrayList<ImageView>();
_imagesNames = new ArrayList<String>();
// Run through the thumbnails dir :
File imagesThumbnailsDir = new File(_imagesThumbnailsDirUri.getPath());
File[] imagesThumbnails = imagesThumbnailsDir.listFiles();
Arrays.sort(imagesThumbnails);
// For each thumbnail :
for(File imageThumbnail : imagesThumbnails)
{
// Check if the image exists :
File image = new File(_imagesDirUri.getPath() + File.separator + imageThumbnail.getName());
if(image.exists()) {
ImageView imageView = new ImageView(_context);
imageView.setImageDrawable(Drawable.createFromPath(imageThumbnail.getAbsolutePath()));
_thumbnails.add(imageView);
_imagesNames.add(imageThumbnail.getName());
}
// If not, delete the thumbnail :
else {
ImageUtils.deleteFile(Uri.fromFile(imageThumbnail));
}
}
}
And so my ImageAdapter's getView function sounds like this :
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
imageView = new ImageView(_context);
imageView.setLayoutParams(new GridView.LayoutParams(80, 80));
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
imageView.setPadding(5, 5, 5, 5);
} else {
imageView = (ImageView) convertView;
}
imageView.setImageDrawable(_thumbnails.get(position).getDrawable());
return imageView;
}
Hope it helps..
Related
I am trying to implement a feature like Instagram or WhatsApp, where the thumbnail of a single image that exists in a folder in android, is shown on top of a list item, more like a sample of what kinds of image are in the folder.
Help me to understand this feature.
How I implemented it. It might not be the best though, but it works.
I fetched the URIs of all the images using MediaStore, you can learn how to use it here.
The First step was done in a background thread to prevent it from blocking the UI thread.
I sorted out the images I got, grouping them in a List<Image>, which would represent a single directory.
I then added the List<Image> into a List<List<Image>>, which served as the overall images that were fetched and have their total size which I used later to track the number of images in the directory.
The code is below.
#Override
public void run() {
Uri storageUri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
storageUri = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);
} else {
storageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
}
// the queries to the MediaStore API (The image details or metadata I need
String[] projection = {
MediaStore.Images.Media._ID,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
MediaStore.Images.Media.SIZE,
MediaStore.Images.Media.DISPLAY_NAME};
// now query the MediaStore API using ContentResolver
Cursor imgCursor = getApplicationContext().getContentResolver().query(storageUri, projection, null, null, null);
int bucketId = imgCursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID);
int imgSize = imgCursor.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE);
int name = imgCursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME);
int bucketName = imgCursor.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
// directoryDictionary is a temporary list of directory names that was found, while querying the MediaStore API
List<String> directoryDictionary = new ArrayList<>();
// generalList is just a list that would represent a general image list, where all images can be found. Just like Whatsapp
List<Image> generalList = new ArrayList<>();
while (imgCursor.moveToNext()) {
long id = imgCursor.getLong(bucketId);
int size = imgCursor.getInt(imgSize);
String fileName = imgCursor.getString(name);
String folderName = imgCursor.getString(bucketName);
// As recommended by the Android developers doc
Uri contentUri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id);
// a single image
Image currentImage = new Image(contentUri, size, fileName, folderName);
// add all images to the general image list, but modifying the directory name
Image genImage = new Image(contentUri, size, fileName, "All Media");
generalList.add(genImage);
int directoryIndex = CollectionUtils.linearSearch(directoryDictionary, folderName);
// if search result (directoryIndex) passes this test, then it means that there is
// no such directory in list of directory names
if (directoryIndex < 0) {
imageDirectoryList.add(new ArrayList<>());
directoryDictionary.add(folderName);
directoryIndex = CollectionUtils.linearSearch(directoryDictionary, folderName);
if (directoryIndex >= 0)
imageDirectoryList.get(directoryIndex).add(currentImage);
} else {
imageDirectoryList.get(directoryIndex).add(currentImage);
}
}
//...then add it if the image list of folder is > 2
if (imageDirectoryList.size() > 2) imageDirectoryList.add(0, generalList);
imgCursor.close();
runOnUiThread(() -> {
// imageAdapter is the RecyclerView's list Adapter.
// notifyDataSetChanged() must be call to refresh list.
imageAdapter.notifyDataSetChanged();
// doViewUpdate was just used to turn on and off the visibility of some views
doViewUpdate();
});
}
I've developed an android app that shows in an adaptor all photos the user has in its device.
This is the code I'm using to read the photos:
Cursor photos;
String pictureCols[] = { MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA, MediaStore.Images.Media.BUCKET_DISPLAY_NAME };
String order = Media.DATE_ADDED + " DESC";
photos = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, pictureCols, null, null, order);
photos.moveToFirst();
photosAdapter.addItems(photos);
And inside the adapter this is the code I use to show them:
public View getView(final int position, View convertView, ViewGroup parent)
{
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View gridView;
if (convertView == null) {
gridView = new View(context);
gridView = inflater.inflate(R.layout.photo_item, null);
}
else
{
gridView = (View) convertView;
}
photoIV = (SquareImageView)gridView.findViewById(R.id.photo);
long photoId = photos.getLong(0);
String thumbURL = "file://"+photos.getString(1);
String thumbCols[] = { MediaStore.Images.Thumbnails._ID, MediaStore.Images.Thumbnails.DATA };
Cursor thumbCursor = MediaStore.Images.Thumbnails.queryMiniThumbnail(context.getContentResolver(), photoId, Thumbnails.MINI_KIND, thumbCols);
if(thumbCursor.getCount() > 0) {
thumbCursor.moveToFirst();
thumbURL = "file://"+thumbCursor.getString(1);
}
thumbCursor.close();
if(!thumbURL.equals(""))
{
mImageOptions = new DisplayImageOptions.Builder()
.cacheInMemory(true)
.cacheOnDisk(true)
.resetViewBeforeLoading(true)
.imageScaleType(ImageScaleType.IN_SAMPLE_INT)
.build();
ImageLoader.getInstance().displayImage(thumbURL, photoIV, mImageOptions);
}
return gridView;
}
This code is working OK on all devices I've tested so far but some users with Samsung Galaxy S7 have reported that most of their photos are shown rotated. I cannot find any documentation related to this issue in S7. Has S7 changed something related to this? Should I read the photos in a different way to get their correct orientation? This code has been working for a long time in a lot of devices.
If you use an image-loading library, and you care about EXIF orientation headers, choose an image-loading library that applies those headers for you (e.g., Picasso, at least for local images). This may require some sort of an opt-in call (e.g., considerExifParams(true), per your comment).
Not all images will have an EXIF orientation header. It depends on whether it is a photo, what sort of camera hardware took the photo, whether the camera app that took the photo rotated the image for you, etc.
Hello kindhearted experts.
I am a newbie to Android Programming world.
I've asked a question about how to list images of phone on a GridView with three columns.
I finally got to the part where I am able to show my images on a GridView, but I am thinking my decoding method isn't efficient enough that it says "The application may be doing too much work on its main thread." and it is obvious the application is really slow.
here is my part of my code:
BitmapFactory.Options bo = new BitmapFactory.Options();
bo.inSampleSize = 8;
Bitmap bmp = BitmapFactory.decodeFile(thumbsDataList.get(position), bo);
Bitmap resized = Bitmap.createScaledBitmap(bmp, 95, 95, true);
imageView.setImageBitmap(resized);
Also, if this part helps you to figure out the issue:
private void getThumbInfo(ArrayList<String> thumbsIDs, ArrayList<String> thumbsDatas){
String[] proj = {MediaStore.Images.Media._ID,
MediaStore.Images.Media.DATA,
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.SIZE};
Cursor imageCursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
proj, null, null, null);
if (imageCursor != null && imageCursor.moveToFirst()){
String thumbsID;
String thumbsImageID;
String thumbsData;
int thumbsIDCol = imageCursor.getColumnIndex(MediaStore.Images.Media._ID);
int thumbsDataCol = imageCursor.getColumnIndex(MediaStore.Images.Media.DATA);
int thumbsImageIDCol = imageCursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME);
int num = 0;
do {
thumbsID = imageCursor.getString(thumbsIDCol);
thumbsData = imageCursor.getString(thumbsDataCol);
thumbsImageID = imageCursor.getString(thumbsImageIDCol);
num++;
if (thumbsImageID != null){
thumbsIDs.add(thumbsID);
thumbsDatas.add(thumbsData);
}
}while (imageCursor.moveToNext());
}
imageCursor.close();
return;
}
If anyone could give me an idea to fix this lag, I will appreciate it very much.
Thank you very much in advance.
I am developing an app that once a button is clicked I go to a new activity where 3 random images are set to an imageView. If the user does not like the 3 images selected, they can then click a button to generate 3 new random images. I am having two problems...
I have the imageView set to a specific size but when the images show up they are sometimes smaller and are showing horizontally. I would like them to show up vertically and all as the size of the imageView. How do I change the code to do this?
I am getting the new images to show up when I click the button but I am getting an error saying that I am running out of memory after I do it a few times. How do I change the code so I stop using all my memory?
Here is my code
public ImageView shirts;
public ImageView pants;
public ImageView shoes;
Button reload;
private Bitmap currentBitmap = null;
String[] projection = new String[]{
MediaStore.Images.Media.DATA,
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.suggested_outfit);
shirts = (ImageView)findViewById(R.id.shirtImage);
pants = (ImageView)findViewById(R.id.pantsImage);
shoes = (ImageView)findViewById(R.id.shoesImage);
shirts.setImageBitmap(getImage());
pants.setImageBitmap(getImage());
shoes.setImageBitmap(getImage());
reload = (Button)findViewById(R.id.getNewOutfit);
reload.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
finish();
startActivity(getIntent());
}
});
}
public Bitmap getImage () {
Uri images = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Cursor cur = getContentResolver().query(images,
projection,"", null, ""
);
final ArrayList<String> imagesPath = new ArrayList<String>();
if (cur.moveToFirst()) {
int dataColumn = cur.getColumnIndex(
MediaStore.Images.Media.DATA);
do {
imagesPath.add(cur.getString(dataColumn));
} while (cur.moveToNext());
}
cur.close();
final Random random = new Random();
final int count = imagesPath.size();
int number = random.nextInt(count);
String path = imagesPath.get(number);
currentBitmap = BitmapFactory.decodeFile(path);
return currentBitmap;
}
}
I read that it isn't good practice to reload the activity but I can't figure out a way to generate 3 new random images. I am open for any suggestions if there is a better way to do this.
Obtaining images through an onClick method would have to have
do {
String path = cur.getString(dataColumn);
if(path.contains("yourDirectory")){ //in your case, your image directory
imagesPath.add(path);
}
} while (cur.moveToNext());
within the requested intent/activity
Decoding Bitmap consumes much memory, on your code you decode Bitmap many times when click button maybe causes OutOfMemory. Try to decode all your Bitmap once times and save them to a list. When a click to generate random Bitmap, you create random index of the list Bitmap and retrieve object by that index. Hope this help!
you can use this utils: image loader
it has memory manager.and you can set imageview when image load completed.
Gist: custom adapter gets file resource indirectly via filepath in database. Inefficiency / memory concerns. Your opinion requested.
References to all searches, related links, and things useful re topic are at post bottom.
Code below works, but several factors are of concern. Need some more experienced eyes on this please to suggest improvement or potential errors to avoid. App doesn't need to be a content provider (data sourced local to app only). The ListView in question will be very light weight with only about 5 to max 10 entries. (I left out the database stuff because it works.)
Overview:
DataBase contains some text and an Image File path. - OK
image files are stored on device (SD card / external storage, where ever). - OK
That the files are not in the database makes this different than a normal SimpleCursorAdapter - have to pull the image file. Added overhead of making it into a thumbnail before populating the listview.
As said, it's light, however, even with only one or two entries, the VM is burping. I suspect it's all the memory joggling related to the Bitmaps:
08-27 19:53:14.273: I/dalvikvm-heap(11900): Grow heap (frag case) to 4.075MB for 1228816-byte allocation
08-27 19:53:14.393: D/dalvikvm(11900): GC_CONCURRENT freed <1K, 5% free 4032K/4244K, paused 13ms+3ms, total 116ms
/* myTextAndImageCursorAdapter.java */
import android.widget.SimpleCursorAdapter;
//import android.support.v4.widget.SimpleCursorAdapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.database.Cursor;
import java.io.File;
import android.widget.ImageView;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import static android.media.ThumbnailUtils.extractThumbnail;
public class TextAndImageCursorAdapter extends SimpleCursorAdapter {
private Context context;
private int layout;
public TextAndImageCursorAdapter (Context ctx, int layout, Cursor c, String[] from, int[] to) {
super(context, layout, c, from, to);
this.context = ctx;
this.layout = layout;
}
#Override
public View newView(Context ctx, Cursor cursor, ViewGroup parent) {
Cursor c = getCursor();
final LayoutInflater inflater = LayoutInflater.from(ctx);
View vView = inflater.inflate(layout, parent, false);
int iCol_Text = c.getColumnIndex(DBCOL_TEXT);
int iCol_Image = c.getColumnIndex(DBCOL_IMAGE);
String sText = c.getString(iCol_Text);
String sFileAndPath_Image = c.getString (iCol_Image); //// sImage path & file
TextView tvText = (TextView) v.findViewById(R.id.gui_text);
if (tvText != null) {
tvText.setText(sSomeText);
}
ImageView ivImage (ImageView) v.findViewById(R.id.gui_image);
if (ivImage != null) {
ivImage.setImage (mySetImage (sFileAndPath_Image) );
}
return vView;
}
#Override
public void bindView(View v, Context ctx, Cursor c) {
//// ( like newView(), without an inflater, view, or return )
int iCol_Text = c.getColumnIndex(DBCOL_TEXT);
int iCol_Image = c.getColumnIndex(DBCOL_IMAGE);
String sText = c.getString(iCol_Text);
String sFileAndPath_Image = c.getString (iCol_Image); //// path & file
TextView tvText = (TextView) v.findViewById(R.id.gui_text);
if (tvText != null) {
tvText.setText(sSomeText);
}
ImageView ivImage (ImageView) v.findViewById(R.id.gui_image);
if (ivImage != null) {
ivImage.setImageBitmap ( mySetImage ( sFileAndPath_Image ) ) ;
}
}
/////
/////
protected Bitmap mySetImage ( String path ) {
int width = 60; int height = 40 ;
File imgFile = new File ( path ); //// usually like: \sdcard0\wherever\filename1234.bmp
Bitmap myBitmap = null;
if( imgFile.exists() )
{
myBitmap = BitmapFactory.decodeFile ( imgFile.getAbsolutePath () );
}
else
Log.d ("oops", "no image file ... using default.");
myBitmap = getTheDefaultImage (); //// not shown - this is arbitrary
}
imgFile.close();
return ( extractThumbnail ( myBitmap, width, height ) ) ;
}
}
[EDIT - added links]
Search Criteria:
"
Android custom simplecursoradapter with image from file with path in database
"
The nearest hit, but attempts to pull image from res, not from external / sd store (unanswered):
SimpleCursorAdapter how to show an image?
Also a near hit / miss - similar algo (unanswered) references 4):
Customizing list shown from SimpleCursorAdapter using ViewBinder
Almost, but OP's code doesn't work, (no working answer):
Load Image in a custom list by SimpleCursorAdapter
Working for OP, but uses JSON for remote retrieval, not local (maybe this could be tweaked, but it's not clear to me how).
How to show images in imageview in simple adapter?
Not quite, but again close:
ListView scroll slow while loading image from Internal Storage
Image Loader problems (references 2):
Imageloader not loading image on real device
Related links:
Android Custom Cursor Adapter
Android: Issue with newView and bindView in custom SimpleCursorAdapter
Similarly named hits, but unrelated to my specific questions - these usually refer to in-app RESources:
show image from database where you saved the path of image
Custom SimpleCursorAdapter error
Custom SimpleCursorAdapter, database query and NullPointerException
nullPointerException with extended SimpleCursorAdapter
Android SimpleCursorAdapter - Adding conditional images
External References:
0) Simple intro tut on custom cursor adapters
http://thinkandroid.wordpress.com/2010/01/11/custom-cursoradapters/
1) Romain Guy - basic layout ... 2 txts, 1 image
http://www.curious-creature.org/2009/02/22/android-layout-tricks-1/
2) AQuery (Android Query)
http://code.google.com/p/android-query/wiki/ImageLoading
3) Android thumbnails
http://developer.android.com/reference/android/media/ThumbnailUtils.html
4) Cust. listview with an "on/off" star image:
http://enjoyandroid.wordpress.com/2012/03/12/customizing-simple-cursor-adapter/
Two things you can do:
1) Use the ViewHolder pattern, cache the LayoutInfalter and most important: don't bind data twice:
/* ... imports */
import static android.media.ThumbnailUtils.extractThumbnail;
public class TextAndImageCursorAdapter extends SimpleCursorAdapter {
private LayoutInflater mLayoutInflater;
private Context context;
private int layout;
private class ViewHolder {
TextView textView;
ImageView imageView;
ViewHolder(View v) {
textView = (TextView) v.findViewById(R.id.gui_text);
imageView = (ImageView) v.findViewById(R.id.gui_image);
}
}
public TextAndImageCursorAdapter (Context ctx, int layout, Cursor c, String[] from, int[] to) {
super(ctx, layout, c, from, to);
this.context = ctx;
this.layout = layout;
mLayoutInflater = LayoutInflater.from(ctx);
}
#Override
public View newView(Context ctx, Cursor cursor, ViewGroup parent) {
View vView = mLayoutInflater.inflate(layout, parent, false);
vView.setTag( new ViewHolder(vView) );
// no need to bind data here. you do in later
return vView;// **EDITED:**need to return the view
}
#Override
public void bindView(View v, Context ctx, Cursor c) {
// you might want to cache these too
int iCol_Text = c.getColumnIndex(DBCOL_TEXT);
int iCol_Image = c.getColumnIndex(DBCOL_IMAGE);
String sText = c.getString(iCol_Text);
String sFileAndPath_Image = c.getString (iCol_Image); //// path & file
ViewHolder vh = (ViewHolder) v.getTag();
vh.textView.setText(sSomeText);
vh.imageView.setImageBitmap ( mySetImage ( sFileAndPath_Image ) );
}
}
2) This is really important: don't create a thumbnail on every bind. you need to cache the result:
private void setThumbnail(String path, Bitmap b) {
// save thumbnail to some kind of cache
// see comment below
}
private Bitmap getThumbnail(String path) {
Bitmap thumbnail = null;
// try to fetch the thumbnail from some kind of cache
// see comment below
return thumbnail;
}
protected Bitmap mySetImage ( String path ) {
int width = 60; int height = 40 ;
Bitmap thumbnail = getThumbnail(path); // try to fetch thumbnail
if (thumbnail != null) return thumbnail;
File imgFile = new File ( path ); //// usually like: /sdcard/wherever/filename1234.bmp
Bitmap myBitmap = null;
if( imgFile.exists() ) {
myBitmap = BitmapFactory.decodeFile ( imgFile.getAbsolutePath () );
} else {
Log.d ("oops", "no image file ... using default.");
myBitmap = getTheDefaultImage (); //// not shown - this is arbitrary
}
imgFile.close();
thumbnail = extractThumbnail ( myBitmap, width, height );
myBitmap.recycle();
setThumbnail(path, thumbnail); // save thumbnail for later reuse
return thumbnail;
}
Depending on you use case, you want to fill getThumbnail() and setThumbnail() with some kind of LruCache:
There is a in memory LruCache available in the android API and in support lib: https://developer.android.com/reference/android/util/LruCache.html
Jake made an persistent DiskLruCache: https://github.com/JakeWharton/DiskLruCache
EDIT :
#Override
public View newView(Context ctx, Cursor cursor, ViewGroup parent) {
View vView = mLayoutInflater.inflate(layout, parent, false);
vView.setTag( new ViewHolder(vView) );
// no need to bind data here. you do in later
return vView;// **EDITED:**need to return the view
}