在Android的應用中實現網狀圖片非同步載入的方法_java

來源:互聯網
上載者:User

前言
其實很幸運,入職一周之後就能跟著兩個師兄做android開發,師兄都是大神,身為小白的我只能多多學習,多多努力。最近一段時間都忙的沒機會總結,今天剛完成了android用戶端圖片非同步載入的類,這裡記錄一下(ps:其實我這裡都是參考網上開源實現)


原理
在ListView或者GridView中載入圖片的原理基本都是一樣的:

    先從記憶體緩衝中擷取,取到則返回,取不到進行下一步
    從檔案快取中擷取,取到則返回並更新到記憶體緩衝,取不到則進行進行下一步
    從網路上下載圖片,並更新記憶體緩衝和檔案快取


流程圖如下:

同時,要注意線程的數量。一般在listview中載入圖片,大家都是開啟新的線程去載入,但是當快速滑動時,很容易造成OOM,因此需要控制線程數量。我們可以通過線程池控制線程的數量,具體線程池的大小還需要根據處理器的情況和業務情況自行判斷

建立線程池的方法如下:

   

ExecutorService executorService = Executors.newFixedThreadPool(5); // 5是可變的 

檔案快取類

   

 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 images       if (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 code       String 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();         }       }     }   } 

記憶體緩衝類
這裡使用了軟引用,Map<String, SoftReference<Bitmap>> cache,可以google一下軟引用的機制,簡單的說:實現了map,同時當記憶體緊張時可以被回收,不會造成記憶體泄露

   

 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<String, SoftReference<Bitmap>> cache = Collections         .synchronizedMap(new LinkedHashMap<String, SoftReference<Bitmap>>(             10, 1.5f, true));        public Bitmap get(String id) {       if (!cache.containsKey(id)) {         return null;       }          SoftReference<Bitmap> ref = cache.get(id);          return ref.get();     }        public void put(String id, Bitmap bitmap) {       cache.put(id, new SoftReference<Bitmap>(bitmap));     }        public void clear() {       cache.clear();     }   } 

圖片載入類

  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<ImageView, String> imageViews = Collections         .synchronizedMap(new WeakHashMap<ImageView, String>());        /**      * 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 cache         imageView.setImageBitmap(bitmap);       } else {         // Display image from File cache or Network         queuePhoto(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 cache       Bitmap bmp = decodeFile(f);       if (bmp != null) {         return bmp;       }          // From Network       try {         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 size         FileInputStream 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;       }          @Override       public void run() {         // Abort current thread if Image View reused         if (imageViewReused(photoToLoad)) {           return;         }            Bitmap bitmap = getBitmap(photoToLoad.url);            // Update Memory         memoryCache.put(photoToLoad.url, bitmap);            if (imageViewReused(photoToLoad)) {           return;         }            // Don't change UI in children thread         BitmapDisplayer 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;         }            @Override         public void run() {           if (imageViewReused(photoToLoad)) {             return;           }              if (bitmap != null) {             photoToLoad.imageView.setImageBitmap(bitmap);           } else {             photoToLoad.imageView.setImageResource(DEFAULT_BG);           }         }          }     }   } 

調用方法

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.