Home
› Uncategorized
In the last exercise of "Implement Android Gallery widget with scale-down bitmap", the bitmap will be loaded and scaled every-time getView() of GalleryBaseAdapter called. The side-effect is the gallery widget stop a moment whenever a new a new item come-out.
The LruCache class (also available in the Support Library for use back to API Level 4) is particularly well suited to the task of caching bitmaps, keeping recently referenced objects in a strong referenced LinkedHashMap and evicting the least recently used member before the cache exceeds its designated size. ~ reference: http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html#memory-cache.
In this exercise, two Gallery widget were implemented. In the video shown below, the upper one is original gallery, the lower one is gallery with cached bitmaps. It can be noted that the cached gallery need more time to be loaded in first loading, but swipe much more smooth.
Main activity.
Modify the layout to have two gallery.
android.util.LruCache is needed in the code, modify AndroidManifest.xml to have minSdkVersion and targetSdkVersion of "13".
Download the files.
Please note that this approach have it's own trade-off: if you request cacheSize too much, it will make your app causing java.lang.OutOfMemory exceptions, if too small, it will cause additional overhead. In my own openion, if you have predictable images (or resources) needed for caching, it's a good choice.
Read more: LruCache with different size
The LruCache class (also available in the Support Library for use back to API Level 4) is particularly well suited to the task of caching bitmaps, keeping recently referenced objects in a strong referenced LinkedHashMap and evicting the least recently used member before the cache exceeds its designated size. ~ reference: http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html#memory-cache.
In this exercise, two Gallery widget were implemented. In the video shown below, the upper one is original gallery, the lower one is gallery with cached bitmaps. It can be noted that the cached gallery need more time to be loaded in first loading, but swipe much more smooth.
Main activity.
package com.example.androidgallery; import java.io.File; import java.lang.ref.WeakReference; import java.util.ArrayList; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.app.Activity; import android.app.ActivityManager; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.util.LruCache; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Gallery; import android.widget.ImageView; import android.widget.LinearLayout; public class MainActivity extends Activity { public class GalleryBaseAdapter extends BaseAdapter { ArrayList<String> GalleryFileList; Context context; GalleryBaseAdapter(Context cont){ context = cont; GalleryFileList = new ArrayList<String>(); } @Override public int getCount() { return GalleryFileList.size(); } @Override public Object getItem(int position) { return GalleryFileList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { Bitmap bm = decodeSampledBitmapFromUri(GalleryFileList.get(position), 200, 200); LinearLayout layout = new LinearLayout(context); layout.setLayoutParams(new Gallery.LayoutParams(250, 250)); layout.setGravity(Gravity.CENTER); ImageView imageView = new ImageView(context); imageView.setLayoutParams(new Gallery.LayoutParams(200, 200)); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); imageView.setImageBitmap(bm); layout.addView(imageView); return layout; } public void add(String newitem){ GalleryFileList.add(newitem); } } public class CacheGalleryBaseAdapter extends GalleryBaseAdapter{ CacheGalleryBaseAdapter(Context cont) { super(cont); } @Override public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView = new ImageView(context); //--- // Use the path as the key to LruCache final String imageKey = GalleryFileList.get(position); final Bitmap bm = getBitmapFromMemCache(imageKey); if (bm == null){ BitmapWorkerTask task = new BitmapWorkerTask(imageView); task.execute(imageKey); } LinearLayout layout = new LinearLayout(context); layout.setLayoutParams(new Gallery.LayoutParams(250, 250)); layout.setGravity(Gravity.CENTER); imageView.setLayoutParams(new Gallery.LayoutParams(200, 200)); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); imageView.setImageBitmap(bm); layout.addView(imageView); return layout; } } GalleryBaseAdapter myGalleryBaseAdapter; CacheGalleryBaseAdapter myCacheGalleryBaseAdapter; Gallery myPhotoGallery, myFastGallery; private LruCache<String, Bitmap> mMemoryCache; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myPhotoGallery = (Gallery)findViewById(R.id.photogallery); myFastGallery = (Gallery)findViewById(R.id.fastgallery); myGalleryBaseAdapter = new GalleryBaseAdapter(this); myCacheGalleryBaseAdapter = new CacheGalleryBaseAdapter(this); String ExternalStorageDirectoryPath = Environment .getExternalStorageDirectory() .getAbsolutePath(); String targetPath = ExternalStorageDirectoryPath + "/test/"; File targetDirector = new File(targetPath); File[] files = targetDirector.listFiles(); for (File file : files){ myGalleryBaseAdapter.add(file.getPath()); myCacheGalleryBaseAdapter.add(file.getPath()); } myPhotoGallery.setAdapter(myGalleryBaseAdapter); myFastGallery.setAdapter(myCacheGalleryBaseAdapter); // Get memory class of this device, exceeding this amount will throw an // OutOfMemory exception. final int memClass = ((ActivityManager)getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass(); // Use 1/8th of the available memory for this memory cache. final int cacheSize = 1024 * 1024 * memClass / 8; mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { protected int sizeOf(String key, Bitmap bitmap) { // The cache size will be measured in bytes rather than number of items. return bitmap.getByteCount(); } }; } class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap>{ private final WeakReference<ImageView> imageViewReference; public BitmapWorkerTask(ImageView imageView) { // Use a WeakReference to ensure the ImageView can be garbage collected imageViewReference = new WeakReference<ImageView>(imageView); } @Override protected Bitmap doInBackground(String... params) { final Bitmap bitmap = decodeSampledBitmapFromUri(params[0], 200, 200); addBitmapToMemoryCache(String.valueOf(params[0]), bitmap); return bitmap; } @Override protected void onPostExecute(Bitmap bitmap) { if (imageViewReference != null && bitmap != null) { final ImageView imageView = (ImageView)imageViewReference.get(); if (imageView != null) { imageView.setImageBitmap(bitmap); } } } } public void addBitmapToMemoryCache(String key, Bitmap bitmap) { if (getBitmapFromMemCache(key) == null) { mMemoryCache.put(key, bitmap); } } public Bitmap getBitmapFromMemCache(String key) { return (Bitmap) mMemoryCache.get(key); } public Bitmap decodeSampledBitmapFromUri(String path, int reqWidth, int reqHeight) { Bitmap bm = null; // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(path, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; bm = BitmapFactory.decodeFile(path, options); return bm; } public int calculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { if (width > height) { inSampleSize = Math.round((float)height / (float)reqHeight); } else { inSampleSize = Math.round((float)width / (float)reqWidth); } } return inSampleSize; } }
Modify the layout to have two gallery.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Gallery without Cache" /> <Gallery android:id="@+id/photogallery" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Gallery with Cache" /> <Gallery android:id="@+id/fastgallery" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout>
android.util.LruCache is needed in the code, modify AndroidManifest.xml to have minSdkVersion and targetSdkVersion of "13".
Download the files.
Please note that this approach have it's own trade-off: if you request cacheSize too much, it will make your app causing java.lang.OutOfMemory exceptions, if too small, it will cause additional overhead. In my own openion, if you have predictable images (or resources) needed for caching, it's a good choice.
Read more: LruCache with different size
-- Delivered by Feed43 service
Related Posts
There is no other posts in this category.Popular
-
Password Pro v3.5.6 iPad iPhone iPod TouchPassword Pro v3.5.6 iPad iPhone iPod Touch Title: Password Pro. Version: 3.5.6 OS: iPad/iPhone/iPod…
-
Ripple Lock v1.6Ripple Lock v1.6 Requirements: for Android version 2.1 and higher Overview: Is still envy of the br…
-
Adobe Photoshop Express v1.3.2 for AndroidAdobe Photoshop Express v1.3.2 for Android You like to edit a personal photo belongs to you? But wa…
-
Bootanimation for Android PhoneBootanimation for Android Phone Bootanimation is one of the animation that appears at the first ti…
-
How To Upgrade OS Android Samsung Galaxy Fit from Froyo to Gingerbread?How To Upgrade OS Android Samsung Galaxy Fit from Froyo to Gingerbread? Since you do not understand…
-
Angry Birds Seasons: Year of the Dragon v2.2.0 for AndroidAngry Birds Seasons: Year of the Dragon v2.2.0 for Android Requires Android:1.6 and up v2.2.0 chang…
-
Titanium Backup 4.1.8 + keyTitanium Backup is the most powerful backup tool on Android, and then some. You can backup, restor…
Post a Comment
Post a Comment