1. 程式人生 > >Android自制圖片的三級快取(程式碼+講解)

Android自制圖片的三級快取(程式碼+講解)

Android的圖片三級快取機制

首先
圖片的三計劃快取的概念
泛指的是 -記憶體快取 -本地快取 -網路快取

記憶體快取的概念
應用程式在執行時 WindowMeanger會分配給 應用 相應的執行時記憶體
執行是記憶體的大小根據android版本有關係

本地快取的概念
本地快取是儲存在硬體上的資料

網路快取的概念
圖片儲存在網路上,需要下載

小結
這三種快取的概念以上以及陳述了,既然我們要做一個服務於圖片的快取,那麼
我們就要應用起來這三種快取到 我們的這個 demo裡面
要應用它 首先 我們做一下專案規劃 這個快取 每一個快取都要是個單獨的類
保持封裝性 然後呼叫的時候要簡單 一行程式碼就呼叫
那麼我們 還要做一個 proxy
好 下面開始

記憶體設計程式碼


import android.graphics.Bitmap;
import android.support.v4.util.LruCache;
/**
 * LruCache工具類
 * @author 浩
 *
 */
public class MemoryCacheUtils {

    private LruCache<String, Bitmap> lruCache;//集合

    public MemoryCacheUtils() {
        int maxSize = (int) Runtime.getRuntime().maxMemory();
        lruCache = new
LruCache<String, Bitmap>(maxSize){ @Override protected int sizeOf(String key, Bitmap value) { // TODO Auto-generated method stub return value.getRowBytes() * value.getHeight(); } }; } /** * 根據url從記憶體中得到快取圖片 * @param
url * @return */
public Bitmap getBitmapFromUril(String url) { // TODO Auto-generated method stub return lruCache.get(url); } /** * 根據url,和bitmp在記憶體中儲存一份bitmap * @param url * @param bitmap */ public void putBitmap2Memory(String url, Bitmap bitmap) { //每個應用佔多少記憶體:16MB lruCache.put(url, bitmap); } }

本地快取設計

mport android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.widget.ImageView;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class LocalCacheUtils {
    /**
     * 本地快取工具類
     * 
     * @author 王浩
     *
     */

    private static final String ATGUIT_DIR = "/mnt/sdcard/beijingnews/";

    /**
     * 根據Bitmap儲存圖片到本地
     * 
     * @param url
     * @param bitmap
     */
    public void putBitmap2Local(String url, Bitmap bitmap) {
        // TODO Auto-generated method stub
        try {
            // String name = MD5Encoder.encode(url);
            // /mnt/sdcard/beijingnews/lskkskklllkk(md5加密)
            File file = new File(ATGUIT_DIR, url);
            // mnt/sdcard/beijingnews/建立
            File parentFile = file.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }

            // 圖片就儲存到sdcard了
            FileOutputStream stream = new FileOutputStream(file);

            bitmap.compress(CompressFormat.JPEG, 100, stream);

            stream.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 根據uri取對應的圖片
     * 
     * @param url
     * @return
     */
    public Bitmap getBitmapFromUrl(String url, ImageView imageView, int tag) {
        try {
            File file = new File(ATGUIT_DIR, url);
            if (file.isFile()) {
                Bitmap bitmap = null ;
                FileInputStream fis = new FileInputStream(file);
                fis.close();
                return bitmap;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}

網路快取設計


import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * 網路快取圖片的工具類
 *
 * @author 王浩
 */
public class NetCatchUtils {

    /**
     * 網路請求圖片成功
     */
    public static final int SUCESS = 0;
    /**
     * 網路請求圖片失敗
     */
    public static final int FAIL = 1;
    private Handler handler;
    /**
     * 本地快取工具類
     */
    private LocalCacheUtils localCacheUtils;
    /**
     * 記憶體快取工具
     */
    private MemoryCacheUtils memoryCacheUtils;

    public NetCatchUtils(Handler handler, LocalCacheUtils localCacheUtils,
                         MemoryCacheUtils memoryCacheUtils) {
        // TODO Auto-generated constructor stub
        this.handler = handler;
        this.localCacheUtils = localCacheUtils;
        this.memoryCacheUtils = memoryCacheUtils;
    }

    /**
     * 根據圖片路徑,請求網路圖片
     *
     * @param url
     * @param position
     * @return
     */
    public Bitmap getBitmapFromUrl(String url, int position, int tag,
                                   Activity ac, ImageView tv_image) {
        new Thread(new MyRunnable(url, position, tag, ac, tv_image)).start();

        return null;
    }

    class MyRunnable implements Runnable {

        private String url;
        private int position;
        private int tag;
        private Activity ac;
        private ImageView tv_image;

        public MyRunnable(String url, int position, int tag, Activity ac,
                          ImageView tv_image) {



            this.url = url;
            this.position = position;
            this.tag = tag;
            this.ac = ac;
            this.tv_image = tv_image;
        }


        /**
         * 處理大圖片載入問題
         */
        @Override
        public void run() {
            HttpURLConnection con = null;
            try {

                  con = (HttpURLConnection) new
                        URL(url).openConnection();

                int code = con.getResponseCode();


                if (200 == code) {
                    InputStream is = con.getInputStream();

                    Options opts = new Options();

                    // 根據計算出的比例進行縮放
                    int scale = ImageUtils.getScare(url, ac);
                    opts.inSampleSize = scale;

                    Bitmap bm = BitmapFactory.decodeStream(is, null, opts);

                    // 將bm發生給主執行緒用於顯示圖片,更新UI
                    Message msg = Message.obtain();
                    msg.obj = bm;
                    msg.arg1 = tag;
                    msg.arg2 = position;



                    tv_image.post(new Action(bm, tv_image));
//                    if(handler!=null) {
//                        tv_image.post(new Action(bm, tv_image));
//                        //handler.sendMessage(msg);
//                    } else {
//                        Utils.log2("tv_image:" + bm + "————tv_image:" + tv_image);
//                        //tv_image.setImageBitmap(bm);
//
//
//                    }

                    // 儲存一份在記憶體
                    memoryCacheUtils.putBitmap2Memory(url, bm);
                    // 儲存一份在本地(Sdcard)
                    localCacheUtils.putBitmap2Local(url, bm);

                }
            } catch (Exception e) {
//                e.printStackTrace();
            }

        }

    }


    /**
     * 在主執行緒更新UI
     */
    class Action implements Runnable{

        private Bitmap  bit ;
        private ImageView img  ;

        public Action(Bitmap bit,ImageView img) {
            this.bit  = bit;
            this.img  = img;
        }


        @Override
        public void run() {

            img.setImageBitmap(bit);
        }
    }

}

代理者設計


/**
 * 三級快取工具類
 * 
 * @author wanghao
 *
 */
public class ImageCacheProxy {

    public static final int LARGE_PHOTO = -11 ;
    /**
     * 一級本地快取
     */
    LocalCacheUtils localCacheUtils;
    /**
     * 二級記憶體快取
     */
    private MemoryCacheUtils memoryCacheUtils;
    /**
     * 三級網路獲取圖片
     */
    private NetCatchUtils netUtils ;
    /**
     * 初始化三級快取
     * @param handler
     */
    public ImageCacheProxy() {
        localCacheUtils = new LocalCacheUtils();
        memoryCacheUtils = new MemoryCacheUtils();
        netUtils = new NetCatchUtils(null, localCacheUtils, memoryCacheUtils);
    }



        /**
         * @param tv_image 要把bit替換成image的image
         * @param url 請求圖片的地址
         * @param position 給圖片做的tag  方便 handler ,裡面 去取
         * @param tag arg1的標記
         */
    public void imageLoader(ImageView tv_image, String url, int position, int tag ,Activity ac) {
        Bitmap bit;

        bit = localCacheUtils.getBitmapFromUrl(url,tv_image,tag);
        if (bit != null) {
            tv_image.setImageBitmap(bit);
            return;
        }
        bit = memoryCacheUtils.getBitmapFromUril(url);
        if (bit != null) {
            tv_image.setImageBitmap(bit);
            return;
        }
        netUtils.getBitmapFromUrl(url, position, tag ,ac,tv_image);
    }


}

這就OK了 呼叫 只需要一行程式碼loader下 就行了

附上我寫的 demo project 地址

本篇部落格結束
如果覺得對你有幫助

粉我把
關注更多我的blog.

技術交流群:

部落格圈 493554215

這是一個熱愛分享技術,擁有熱烈學習氛圍的群 ,
博主身為群內的一員感到驕傲
推薦還在路上的夥伴們