Android batch image loading classic series-use LruCache and AsyncTask cache and load images asynchronously,
Use LruCache and AsyncTask to load batch images and meet the following technical requirements:
1. Read the image from the cache. If it is not in the cache, enable AsyncTask to load the image and put it into the cache.
2. Remove invalid asynchronous threads in a timely manner; Ensure that images are not in disorder during asynchronous loading.
3. Only cache the visible part of the current screen and asynchronously load the image
4. Optimize performance to prevent OOM
Case study: photo wall effect
LruCache
Memory Cache Technology, which is used for image cache processing in Android. The main steps are as follows:
(1) set the memory size of the cached image, for example, to 1/8 of the phone memory (when the cached image reaches the preset value, the Code is as follows:
// Obtain the maximum available memory of the application. int maxMemory = (int) Runtime. getRuntime (). maxMemory (); int cacheSize = maxMemory/8; // sets the image cache size to 1/8 mMemoryCache = new LruCache <String, Bitmap> (cacheSize) of the maximum available memory of the program) {@ Override protected int sizeOf (String key, Bitmap bitmap) {return bitmap. getByteCount ();}};
(2) Put the image into the cache (the key-value pairs in LruCache are usually URLs and corresponding images respectively)
MMemoryCache. put (key, bitmap );
(3) retrieving images from the cache
MMemoryCache. get (key );
AsyncTask
For time-consuming operations such as loading images, asynchronous tasks must be used without blocking the UI thread. AsyncTask is a component that can implement asynchronous tasks without using thread + handler. It is relatively simple to use and more lightweight. Perform the following steps to implement AsyncTask:
(1) Extend the sub-AsyncTask, as shown in figure
Class BitmapWorkerTask extends AsyncTask <String, Void, Bitmap>
(2) rewrite several methods in AsyncTask
OnPreExecute (), this method will be called by the UI thread before the actual background operation is executed. You can make some preparations in this method, such as displaying a progress bar on the interface.
DoInBackground (Params...) will be executed after the onPreExecute method is executed. This method runs in the background thread and is mainly responsible for executing time-consuming background computing tasks, such as loading images.
OnPostExecute (Result). After doInBackground is executed, the Result is called by the UI thread. The background computing Result is passed to the UI thread through this method.
(3) execute (Params…) of AsyncTask In the UI thread ...);
Start to execute the asynchronous task and input data to the background task. execution order: onPreExecute () --> doInBackground (Params...) --> onPostExecute (Result)
Experience: loading a large number of images requires that each image be retrieved and run in a background task. Therefore, you need to use a set to record all tasks that are being downloaded or waiting for download.
Set <BitmapWorkerTask> taskCollection = new HashSet <BitmapWorkerTask> ();
When there is no image in the cache, add the task and start asynchronous processing. The fragment code is as follows:
If (bitmap = null) {// if the cache does not contain BitmapWorkerTask task = new BitmapWorkerTask (); taskCollection. add (task); task.exe cute (imageUrl); // execute an asynchronous task and input the loaded image url}
Pay attention to remove completed tasks in a timely manner, as shown in the following code:
protected void onPostExecute(Bitmap bitmap) {….taskCollection.remove(this);}
The part code is as follows:
Public void onScrollStateChanged (AbsListView view, int scrollState) {// download the image only when the GridView is static. When the GridView slides, cancel all the tasks being downloaded if (scrollState = SCROLL_STATE_IDLE) {loadBitmaps (mFirstVisibleItem, mVisibleItemCount);} else {cancelAllTasks (); // cancel all tasks that are being downloaded or waiting for download .}} Public void cancelAllTasks () {if (taskCollection! = Null) {for (BitmapWorkerTask task: taskCollection) {task. cancel (false );}}}
1. MainActivity
Public class MainActivity extends Activity {private GridView mPhotoWall; private PhotoWallAdapter adapter; private ArrayList <File> list; protected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_main); list = new ArrayList <File> (); getAllFiles (new File ("/sdcard"); mPhotoWall = (GridView) findViewById (R. id. photo_wall); adapter = new Ph OtoWallAdapter (this, 0, list, mPhotoWall); mPhotoWall. setAdapter (adapter);}/*** get the specified directory File */private void getAllFiles (File root) {File files [] = root. listFiles (); if (files! = Null) for (File f: files) {if (f. isDirectory () {getAllFiles (f);} else {if (f. getName (). indexOf (". png ")> 0 | f. getName (). indexOf (". jpg ")> 0 | f. getName (). indexOf (". jpeg ")> 0) this. list. add (f) ;}} protected void onDestroy () {super. onDestroy (); adapter. cancelAllTasks (); // end all download tasks when exiting the program }}
2. PhotoWallAdapter Adapter
Public class PhotoWallAdapter extends ArrayAdapter <File> implements OnScrollListener {// records all tasks that are being downloaded or awaiting download. Private Set <BitmapWorkerTask> taskCollection; // core class of image cache technology, used to cache all downloaded images, when the program memory reaches the set value, the minimum number of recently used images will be removed. Private LruCache <String, Bitmap> mMemoryCache; // private GridView mPhotoWall; // The subscript private int mFirstVisibleItem of the first visible image; // how many images can be seen on a screen: private int mVisibleItemCount. Private boolean isFirstEnter = true; ArrayList <File> list = null; public PhotoWallAdapter (Context context, int textViewResourceId, ArrayList <File> objects, GridView photoWall) {super (context, textViewResourceId, objects); mPhotoWall = photoWall; list = objects; taskCollection = new HashSet <BitmapWorkerTask> (); // get the maximum available memory of the application int maxMemory = (int) Runtime. getRuntime (). maxMemory (); int cacheSize = MaxMemory/8; // set the image cache size to 1/8 mMemoryCache = new LruCache <String, Bitmap> (cacheSize) {@ Override protected int sizeOf (String key, bitmap bitmap) {return bitmap. getByteCount () ;}}; mPhotoWall. setOnScrollListener (this);} public View getView (int position, View convertView, ViewGroup parent) {final File url = getItem (position); View view; if (convertView = null) {view = LayoutInflater. From (getContext ()). inflate (R. layout. photo_layout, null);} else {view = convertView;} final ImageView photo = (ImageView) view. findViewById (R. id. photo); // set a Tag for the ImageView to ensure that no disordered photo occurs during asynchronous image loading. setTag (url. getAbsolutePath (); setImageView (url. getAbsolutePath (), photo); return view;}/*** sets an image for ImageView. First, extract the image cache from LruCache and set it to ImageView. If the image is not cached in LruCache, * set a default image for ImageView. * @ Param imageUrl * the URL of the image, used as the key of LruCache. * @ Param imageView * controls used to display images. */Private void setImageView (String imageUrl, ImageView imageView) {Bitmap bitmap = getBitmapFromMemoryCache (imageUrl); if (bitmap! = Null) {imageView. setImageBitmap (bitmap);} else {bitmap = getLoacalBitmap (imageUrl); imageView. setImageResource (R. drawable. empty_photo) ;}}/*** stores an image in LruCache. * @ Param key * The LruCache key. the URL of the image is entered here. * @ Param bitmap * The LruCache key. Here, the Bitmap object downloaded from the network is passed in. * // @ SuppressLint ("NewApi") public void addBitmapToMemoryCache (String key, Bitmap bitmap) {if (getBitmapFromMemoryCache (key) = null) {mMemoryCache. put (key, bitmap) ;}}/*** gets an image from LruCache. If it does not exist, null is returned. * @ Param key * The LruCache key. the URL of the image is entered here. * @ Return corresponds to the Bitmap object of the Input key, or null. * // @ SuppressLint ("NewApi") public Bitmap getBitmapFromMemoryCache (String key) {return mMemoryCache. get (key) ;}@ Override public void onScrollStateChanged (AbsListView view, int scrollState) {// download the image only when the GridView is static, cancel all tasks being downloaded when the GridView slides. if (scrollState = SCROLL_STATE_IDLE) {loadBitmaps (uploads, mVisibleItemCount);} else {cancelAllTasks () ;}}@ Override public void onScroll (AbsListVi Ew view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {mFirstVisibleItem = firstVisibleItem; mVisibleItemCount = visibleItemCount; // The download task should be called in onScrollStateChanged, however, onScrollStateChanged is not called when you enter the program for the first time. // Therefore, the download task is enabled for the first time you enter the program. If (isFirstEnter & amp; visibleItemCount & gt; 0) {loadBitmaps (firstVisibleItem, visibleItemCount); isFirstEnter = false ;}}/*** load a Bitmap object. This method checks the Bitmap objects of ImageView visible on all screens in LruCache. * If any Bitmap object of ImageView is not in the cache, an asynchronous thread is enabled to download the image. ** @ Param firstVisibleItem * subscript of the first visible ImageView * @ param visibleItemCount * Total number of visible elements on the screen */private void loadBitmaps (int firstVisibleItem, int visibleItemCount) {try {for (int I = firstVisibleItem; I <firstVisibleItem + visibleItemCount; I ++) {String imageUrl = list. get (I ). getAbsolutePath (); Bitmap bitmap = getBitmapFromMemoryCache (imageUrl); if (bitmap = null) {// if the cache does not contain BitmapWorkerTask = New BitmapWorkerTask (); taskCollection. add (task); task.exe cute (imageUrl); // execute an asynchronous task and input the loaded image url (the image on the SD card )} else {ImageView imageView = (ImageView) mPhotoWall. findViewWithTag (imageUrl); if (imageView! = Null & bitmap! = Null) {imageView. setImageBitmap (bitmap) ;}}} catch (Exception e) {e. printStackTrace () ;}}/*** cancels all tasks that are being downloaded or waiting for download. */Public void cancelAllTasks () {if (taskCollection! = Null) {for (BitmapWorkerTask task: taskCollection) {task. cancel (false) ;}}/*** the task of downloading images asynchronously. */Class BitmapWorkerTask extends AsyncTask <String, Void, Bitmap> {/*** URL of the image */private String imageUrl; @ Override protected Bitmap doInBackground (String... params) {imageUrl = params [0]; // download the image Bitmap bitmap = getLoacalBitmap (params [0]) in the background; if (bitmap! = Null) {// cache the downloaded image to the LrcCache addBitmapToMemoryCache (params [0], bitmap);} return bitmap;} @ Override protected void onPostExecute (Bitmap bitmap) {super. onPostExecute (bitmap); // locate the corresponding ImageView Control Based on the Tag and display the downloaded image. ImageView imageView = (ImageView) mPhotoWall. findViewWithTag (imageUrl); if (imageView! = Null & bitmap! = Null) {imageView. setImageBitmap (bitmap);} taskCollection. remove (this) ;}} private Bitmap getLoacalBitmap (String url) {try {FileInputStream FCM = new FileInputStream (url); return BitmapFactory. decodeStream (FS); // convert the stream into Bitmap image} catch (FileNotFoundException e) {e. printStackTrace (); return null ;}}}
For more information, clickView Source CodeRun the test in person.
For questions or technical exchanges, please join the official QQ group: (452379712)
Author: Jerry Education
Source: http://www.cnblogs.com/jerehedu/
The copyright of this article belongs to Yantai Jerry Education Technology Co., Ltd. and the blog Park. You are welcome to repost it. However, you must keep this statement without the author's consent and provide the original article connection on the article page, otherwise, you are entitled to pursue legal liability.