Asynchronous loading of Android Network Images

Source: Internet
Author: User

The preface is actually very lucky. After one week of employment, I will be able to develop android with two senior brothers, both of whom are great gods. As a little white, I can only learn more and work harder. I have been busy for some time and have no chance to summarize it. Today I just completed the asynchronous loading of android client images. Here I will record it (ps: Actually, I will refer to the open-source implementation on the Internet)

The principle of loading images in ListView or GridView is basically the same: Get the image from the memory cache first, get it, and return it. If the image cannot be obtained, the next step is to obtain the image from the file cache, if no image is obtained, it is returned and updated to the memory cache. If no image is obtained, download the image from the network and update the memory cache and file cache.
The flowchart is as follows:




Pay attention to the number of threads. Generally, when loading images in the listview, we enable new threads to load images. However, it is easy to cause OOM when sliding fast, so we need to control the number of threads. We can control the number of threads through the thread pool. The specific thread pool size also needs to be determined based on the processor situation and business conditions.
The method for creating a thread pool is as follows:

ExecutorService executorService = Executors. newFixedThreadPool (5); // 5 is variable


File Cache
import java.io.File;import android.content.Context;public class FileCache {private static final String DIR_NAME = "your_dir";private File cacheDir;public FileCache(Context context) {// Find the directory to save cached imagesif (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {cacheDir = new File(android.os.Environment.getExternalStorageDirectory(),DIR_NAME);} else {cacheDir = context.getCacheDir();}if (!cacheDir.exists()) {cacheDir.mkdirs();}}public File getFile(String url) {// Identify images by url's hash codeString filename = String.valueOf(url.hashCode());File f = new File(cacheDir, filename);return f;}public void clear() {File[] files = cacheDir.listFiles();if (files == null) {return;} else {for (File f : files) {f.delete();}}}}


The memory cache class uses soft reference here, Map > Cache, You can google the soft reference mechanism, Simply put: map is implemented, and can be recycled when the memory is insufficient, without causing memory leakage
import java.lang.ref.SoftReference;import java.util.Collections;import java.util.LinkedHashMap;import java.util.Map;import android.graphics.Bitmap;public class MemoryCache {private Map
  
   > cache = Collections.synchronizedMap(new LinkedHashMap
   
    >(10, 1.5f, true));public Bitmap get(String id) {if (!cache.containsKey(id)) {return null;}SoftReference
    
      ref = cache.get(id);return ref.get();}public void put(String id, Bitmap bitmap) {cache.put(id, new SoftReference
     
      (bitmap));}public void clear() {cache.clear();}}
     
    
   
  


Image loading class
package io.yunos.bbs;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.InputStream;import java.io.OutputStream;import java.net.HttpURLConnection;import java.net.URL;import java.util.Collections;import java.util.Map;import java.util.WeakHashMap;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Handler;import android.widget.ImageView;public class ImageLoader {/** * Network time out */private static final int TIME_OUT = 30000;/** * Default picture resource */private static final int DEFAULT_BG = R.drawable.plate_list_head_bg;/** * Thread pool number */private static final int THREAD_NUM = 5;/** * Memory image cache */MemoryCache memoryCache = new MemoryCache();/** * File image cache */FileCache fileCache;/** * Judge image view if it is reuse */private Map
  
    imageViews = Collections.synchronizedMap(new WeakHashMap
   
    ());/** * Thread pool */ExecutorService executorService;/** * Handler to display images in UI thread */Handler handler = new Handler();public ImageLoader(Context context) {fileCache = new FileCache(context);executorService = Executors.newFixedThreadPool(THREAD_NUM);}public void disPlayImage(String url, ImageView imageView) {imageViews.put(imageView, url);Bitmap bitmap = memoryCache.get(url);if (bitmap != null) {// Display image from Memory cacheimageView.setImageBitmap(bitmap);} else {// Display image from File cache or NetworkqueuePhoto(url, imageView);}}private void queuePhoto(String url, ImageView imageView) {PhotoToLoad photoToLoad = new PhotoToLoad(url, imageView);executorService.submit(new PhotosLoader(photoToLoad));}private Bitmap getBitmap(String url) {File f = fileCache.getFile(url);// From File cacheBitmap bmp = decodeFile(f);if (bmp != null) {return bmp;}// From Networktry {Bitmap bitmap = null;URL imageUrl = new URL(url);HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection();conn.setConnectTimeout(TIME_OUT);conn.setReadTimeout(TIME_OUT);conn.setInstanceFollowRedirects(true);InputStream is = conn.getInputStream();OutputStream os = new FileOutputStream(f);copyStream(is, os);os.close();conn.disconnect();bitmap = decodeFile(f);return bitmap;} catch (Throwable ex) {if (ex instanceof OutOfMemoryError) {clearCache();}return null;}}private void copyStream(InputStream is, OutputStream os) {int buffer_size = 1024;try {byte[] bytes = new byte[buffer_size];while (true) {int count = is.read(bytes, 0, buffer_size);if (count == -1) {break;}os.write(bytes, 0, count);}} catch (Exception e) {}}private Bitmap decodeFile(File f) {try {// TODO:Compress image sizeFileInputStream fileInputStream = new FileInputStream(f);Bitmap bitmap = BitmapFactory.decodeStream(fileInputStream);return bitmap;} catch (FileNotFoundException e) {return null;}}private void clearCache() {memoryCache.clear();fileCache.clear();}/** * Task for the queue *  * @author zhengyi.wzy *  */private class PhotoToLoad {public String url;public ImageView imageView;public PhotoToLoad(String url, ImageView imageView) {this.url = url;this.imageView = imageView;}}/** * Asynchronous to load picture *  * @author zhengyi.wzy *  */class PhotosLoader implements Runnable {PhotoToLoad photoToLoad;public PhotosLoader(PhotoToLoad photoToLoad) {this.photoToLoad = photoToLoad;}private boolean imageViewReused(PhotoToLoad photoToLoad) {String tag = imageViews.get(photoToLoad.imageView);if (tag == null || !tag.equals(photoToLoad.url)) {return true;}return false;}@Overridepublic void run() {// Abort current thread if Image View reusedif (imageViewReused(photoToLoad)) {return;}Bitmap bitmap = getBitmap(photoToLoad.url);// Update MemorymemoryCache.put(photoToLoad.url, bitmap);if (imageViewReused(photoToLoad)) {return;}// Don't change UI in children threadBitmapDisplayer bd = new BitmapDisplayer(bitmap, photoToLoad);handler.post(bd);}class BitmapDisplayer implements Runnable {Bitmap bitmap;PhotoToLoad photoToLoad;public BitmapDisplayer(Bitmap bitmap, PhotoToLoad photoToLoad) {this.bitmap = bitmap;this.photoToLoad = photoToLoad;}@Overridepublic void run() {if (imageViewReused(photoToLoad)) {return;}if (bitmap != null) {photoToLoad.imageView.setImageBitmap(bitmap);} else {photoToLoad.imageView.setImageResource(DEFAULT_BG);}}}}}
   
  


Call Method
ImageLoader imageLoader = new ImageLoader(context);imageLoader.disPlayImage(imageUrl, imageView);


Summary It's Okay recently. I have finally started to get busy. I still like the intense pace and can learn more.



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.