1. 程式人生 > >Android --- 簡單實現三級快取

Android --- 簡單實現三級快取

三級快取:

    1、網路快取 從網路獲取資源(非同步載入)
    2、本地快取 從本地獲取資料(File儲存)
    3、記憶體快取 從記憶體獲取資料(LruCache)

1、記憶體快取:LruCache

  主要是用到了LruCache這個類,這個類比較適合用來快取圖片,它會將強引用物件放在LinkedHashMap中,當快取資料大小達到預定值的時候會將在該集合中比較少使用的物件從記憶體中移除。

package com.example.administrator.downloadimgdemo.utils;

import android.graphics.Bitmap;
import
android.util.LruCache; /** * Created by Administrator on 2017/5/4. */ public class MemoryCacheUtil { private LruCache<String, Bitmap> mLruCache; public MemoryCacheUtil() { // maxMemory 是允許的最大值 ,超過這個最大值,則會回收 int maxMemory = (int) Runtime.getRuntime().maxMemory(); int
cacheSize = maxMemory / 8; mLruCache = new LruCache<String, Bitmap>(cacheSize) { /** * 計算每張圖片的大小 * @param key * @param bitmap * @return */ @Override protected int sizeOf(String key, Bitmap bitmap) { return
bitmap.getByteCount(); } }; } /** * 通過url從記憶體中獲取圖片 * * @param url */ public Bitmap getBitmapFromMemory(String url) { return mLruCache.get(url); } /** * 設定Bitmap到記憶體 * * @param url * @param bitmap */ public void setBitmapToMemory(String url, Bitmap bitmap) { if (getBitmapFromMemory(url) == null) { mLruCache.put(url, bitmap); // 設定圖片 } } /** * 從快取中刪除指定的Bitmap * * @param key */ public void removeBitmapFromMemory(String key) { mLruCache.remove(key); } }

使用對應的鍵和值將資料put進集合中,使用get方法再取出來

2、本地快取:File

將網路上獲取下來的資料,儲存在本地檔案中.

package com.example.administrator.downloadimgdemo.utils;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;

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

/**
 * Created by Administrator on 2017/5/4.
 */

public class LocalCacheUtil {

    private String cachePath;

    public LocalCacheUtil(Context context, String uniqueName) {
        cachePath = getCacheDirString(context, uniqueName);
    }


    /**
     * 設定Bitmap資料到本地
     *
     * @param url
     * @param bitmap
     */
    public void setBitmapToLocal(String url, Bitmap bitmap) {
        FileOutputStream fos = null;
        try {
            String fileName = MD5Encoder.encode(url);
            File file = new File(cachePath, fileName);
            File parentFile = file.getParentFile();//獲取上級所有目錄
            if (!parentFile.exists()) {
                // 如果檔案不存在,則建立資料夾
                parentFile.mkdirs();
            }
             fos = new FileOutputStream(file);
            // 將圖片壓縮到本地
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (fos != null) {
                try {
                    fos.close();//關閉流
                    fos = null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /**
     * 通過url獲取Bitmap
     *
     * @param url
     */
    public Bitmap getBitmapFromLocal(String url) {
        try {
            File file = new File(cachePath, MD5Encoder.encode(url));
            if (file.exists()) {
                // 如果檔案存在
                Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file));
                //Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
                return bitmap;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /*獲取快取目錄的路徑:String型別*/
    private String getCacheDirString(Context context, String uniqueName) {
        File file = null;
        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
                || !Environment.isExternalStorageRemovable()) {
            file = new File(context.getExternalCacheDir(), uniqueName);
            //file = new File(Environment.getExternalStorageDirectory(), uniqueName);
        } else {
            file = new File(context.getCacheDir(), uniqueName);
        }

        if (!file.exists()) {
            file.mkdirs();
        }

        return file.getAbsolutePath();
    }
}

MD5工具類:

用於生成儲存的檔名:

package com.example.administrator.downloadimgdemo.utils;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * Created by Administrator on 2017/5/4.
 */

public class MD5Encoder {

    public static String encode(String pwd) {
        StringBuffer sb = new StringBuffer();
        try {
            MessageDigest digest = MessageDigest.getInstance("MD5");
            byte[] bytes = digest.digest(pwd.getBytes("UTF-8"));
            for (int i = 0; i < bytes.length; i++) {
                String s = Integer.toHexString(0xff & bytes[i]);

                if (s.length() == 1) {
                    sb.append("0" + s);
                } else {
                    sb.append(s);
                }
            }
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

}

3、網路快取:AsyncTask非同步請求

 通過url從網路上獲取資源資料,通過非同步AsyncTask拉取資料,同時,如果成功拉取到資料,將資料儲存在本地和記憶體中一份。

package com.example.administrator.downloadimgdemo.utils;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.widget.ImageView;

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

/**
 * Created by Administrator on 2017/5/4.
 */

public class NetCacheUtil {

    private MemoryCacheUtil mMemoryCacheUtil;
    private LocalCacheUtil mLocalCacheUtil;

    public NetCacheUtil(MemoryCacheUtil mMemoryCacheUtil, LocalCacheUtil mLocalCacheUtil) {
        this.mMemoryCacheUtil = mMemoryCacheUtil;
        this.mLocalCacheUtil = mLocalCacheUtil;
    }

    /**
     * 獲取服務端資料
     *
     * @param ivPhoto
     * @param url
     */
    public void getBitmapFromInternet(ImageView ivPhoto, String url) {

        new BitmapAsyncTask().execute(ivPhoto, url); // 開啟AsyncTask

    }

    /**
     * 第一個泛型:引數型別  第二個泛型:更新進度的泛型, 第三個泛型是OnPostExecute的結果
     * Object : 傳入的引數型別
     * Void : 進度
     * Bitmap : 返回型別
     */
    private class BitmapAsyncTask extends AsyncTask<Object, Void, Bitmap> {

        private ImageView ivPhoto;
        private String url;

        /**
         * 執行在子執行緒中:請求資料
         *
         * @param params
         * @return
         */
        @Override
        protected Bitmap doInBackground(Object... params) {

            ivPhoto = (ImageView) params[0]; // 獲取兩個引數
            url = (String) params[1];

            Bitmap bitmap = downloadBitmap(url); // 從網路上載入圖片

            return bitmap;
        }

        /**
         * 在主執行緒中執行 用於更新介面
         *
         * @param bitmap
         */
        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);

            if (bitmap != null) {

                ivPhoto.setImageBitmap(bitmap); // 為ImageView設定圖片

                System.out.println("從網路獲取圖片...");

                // 將獲取到的圖片載入到本地
                mLocalCacheUtil.setBitmapToLocal(url, bitmap);
                // 將獲取到的圖片載入到記憶體
                mMemoryCacheUtil.setBitmapToMemory(url, bitmap);
            }

        }
    }

    /**
     * 根據url從網路上獲取圖片
     *
     * @param imageUrl 圖片路徑
     * @return
     */
    private Bitmap downloadBitmap(String imageUrl) {

        HttpURLConnection conn = null;

        try {
            URL url = new URL(imageUrl);
            conn = (HttpURLConnection) url.openConnection(); // 開啟連線
            conn.setReadTimeout(5000); // 設定讀取超時時間
            conn.setConnectTimeout(5000); // 設定連線超時時間
            conn.setRequestMethod("GET"); // 設定請求方式
            conn.connect(); // 開始連線

            if (conn.getResponseCode() == 200) {
                // 訪問成功
                InputStream is = conn.getInputStream(); // 獲取流資料
                // 對圖片進行壓縮處理
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inSampleSize = 2; // 圖片的寬高都為原來的一半(解析度)
                Bitmap bitmap = BitmapFactory.decodeStream(is, null, options); // 將流資料轉成Bitmap物件

                return bitmap;

            } else {
                // 訪問失敗
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                conn.disconnect(); // 斷開連線
            }
        }
        return null;
    }

}

MyBitmapUtil:整合使用

工具類:MyBitmapUtil:三級快取的工具類

package com.example.administrator.downloadimgdemo.utils;

import android.content.Context;
import android.graphics.Bitmap;
import android.widget.ImageView;

/**
 * Created by Administrator on 2017/5/4.
 */

public class MyBitmapUtil {


    private MemoryCacheUtil mMemoryCacheUtil = null; // 記憶體快取(lrucache)
    private LocalCacheUtil mLocalCacheUtil = null; // 本地快取(file)
    private NetCacheUtil mNetCacheUtil = null; // 網路快取

    public MyBitmapUtil(Context context, String uniqueName) {
        mMemoryCacheUtil = new MemoryCacheUtil();
        mLocalCacheUtil = new LocalCacheUtil(context,uniqueName);
        mNetCacheUtil = new NetCacheUtil(mMemoryCacheUtil, mLocalCacheUtil);
    }

    /**
     * 將圖片資源設定給控制元件
     *
     * @param url
     * @param ivPhoto
     */
    public void display(String url, ImageView ivPhoto) {

        Bitmap bitmap = null;

        // 1.判斷記憶體中是否有快取
        bitmap = mMemoryCacheUtil.getBitmapFromMemory(url); // 從記憶體中獲取Bitmap
        if (bitmap != null) {
            ivPhoto.setImageBitmap(bitmap); // 設定圖片
            System.out.println("從記憶體獲取圖片...");
            return;
        }
        // 2.判斷本地是否有快取
        bitmap = mLocalCacheUtil.getBitmapFromLocal(url); // 從本地快取中獲取Bitmap
        if (bitmap != null) {
            ivPhoto.setImageBitmap(bitmap); // 設定本地圖片
            mMemoryCacheUtil.setBitmapToMemory(url, bitmap); // 設定圖片到記憶體
            System.out.println("從本地獲取圖片...");
            return;
        }
        // 3.從網路獲取資料

        mNetCacheUtil.getBitmapFromInternet(ivPhoto, url); // 設定圖片

    }


}

參考:

相關推薦

Android --- 簡單實現三級快取

三級快取:     1、網路快取 從網路獲取資源(非同步載入)     2、本地快取 從本地獲取資料(File儲存)     3、記憶體快取 從記憶體獲取資料(LruCache) 1、記憶體快取:LruCache   主要是用到了LruCache這

Android --- 簡單實現三級快取LruCache

  三級快取:     1、網路快取 從網路獲取資源     2、本地快取 從本地獲取資料     3、記憶體快取 從記憶體獲取資料   記憶體快取:主要是用到了LruCache這個類,這個類比較適合用來快取圖片,它會將強引用物件放在LineedHashMap中,當快取資料大小達到預定值的時候會將在該

Android 簡單實現三級列表

第一步對應在  main 下面建立一個assets檔案 ,裡面放入自己寫好的檔案 裡面對應的事城市 佈局就一個textview <TextView android:id="@+id/tv_address" android:textS

自己動手實現Android中的三級快取框架

前言 2018年過去了,很久之前就希望自己可以潛心研究原始碼,研究技術,但是空閒時間不是看電影,就是玩遊戲都沒有認真看技術方面的東西感覺很內疚,2019年一定要好好的研究端正態度,認真學習技術。 為什麼要三級快取 有時候Android應用中要獲取比較大的資料,比如說圖片流,短視訊流等,如果每次都從網路上

Android簡單實現 快取資料

前言 1、每一種要快取的資料都是有對應的versionCode,通過versionCode請求網路獲取是否需要更新 2、提前將要快取的資料放入assets資料夾中,打包上線。 快取設計 程式碼實現 /** * Created by hua

Android簡單實現將手機圖片上傳到server中

sdk etc mov 創建 ast bmi 以及 lena ews 在本例中。將會簡單的實現安卓手機將圖片上傳到server中。本例使用到了 server端:PHP+APACHE 客戶端:JAVA 先簡單實現一下server端的上傳並測試上傳

簡單實現三級導航欄

idt wid mar play png add div image red 簡單實現三級導航欄效果,如圖: 代碼如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"&g

android簡單 實現 日曆,生日 原生簡單輕鬆搞定

先看下佈局    對應的一個輸入框點選觸發 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/an

Android簡單實現本地圖片和視訊選擇器功能

哈嘍,大家好,好久不見了,很久沒有更新 Android 方面的技術文章了,最近在忙公司的 AR 類的新產品,其中涉及到本地圖片和視訊的選擇和上傳功能。至於為什麼不用系統提供的圖片和視訊選擇器,原因你懂的,系統提供的選擇器只能通過 Intent 方式去獲取,這意味

Android簡單實現水波紋

public class WeatherView extends View { private Path path1,path2; private Paint paint1,paint2; private float Φ; pub

Android 簡單實現可全屏拖動,可點選的View

首先,我們都知道,拖動一個view,需要給它設定touchListener,或者重寫他的touchEvent。我們以ImageView為例,自定義一個DragView,繼承ImageView。 單純的只是想讓view拖動,我們只需要在ACTION_DOWN

Android 簡單實現ListView頂部懸浮效果

首先上效果圖,實現如下效果:起初在網上搜了下實現這樣的效果,美團網,大眾點評的“購買框”懸浮效果也是這樣的,不過作者實現比較麻煩,自己想了想就根據ListView提供的一些特性進行了簡單實現。整個主要佈局就是一個ListView,如果listview的上面有內容且高度比較高,可以把它當做listview的he

Android 簡單實現Activity介面變暗效果

效果圖: 程式碼實現如下: private void dimBackground(final float from, final float to) { final W

簡單實現Redis快取中的排序功能(三)

在實現快取排序功能之前,必須先明白這一功能的合理性。不妨思考一下,既然可以在資料庫中排序,為什麼還要把排序功能放在快取中實現呢?這裡簡單總結了兩個原因:首先,排序會增加資料庫的負載,難以支撐高併發的應用;其次,在快取中排序不會遇到表鎖定的問題。Redis恰好提供了排序功能

Android簡單實現BroadCastReceiver廣播機制

Android中廣播的作用是非常明顯的,當我們收到一條資訊,可能我們的應用需要處理一些資料,可能我們開機,我們的應用也需要處理一些資料,這裡都用到了廣播機制,這裡簡單的實現了一個自定義廣播,看例項: MyBroadcastReceiver.java pac

Android簡單實現下拉重新整理和上拉重新整理

先把佈局檔案裡面新增一個ListView控制元件, <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.a

Android簡單實現高德地圖顯示及定位

1、要實現高德地圖的定位,首先要下載高德地圖的SDK 下載地址:http://lbs.amap.com/api/android-location-sdk/download/ 然後在高德地圖官網上登入你註冊的賬號並且去控制檯

Android 圖片的三級快取 及 圖片壓縮

為什麼需要圖片快取 android預設給每個應用只分配16M的記憶體,所以如果載入過多的圖片,為了防止記憶體溢位,應該將圖片快取起來。圖片的三級快取分別是: 記憶體快取 本地快取 網路快取 其中,記憶體快取應優先載

Android簡單實現Socket通訊,客戶端連線伺服器後,伺服器向客戶端傳送文字資料

案例實現的是簡單的Socket通訊,當客戶端(Android客戶端)連線到指定伺服器以後,伺服器向客戶端傳送一句話文字資訊(你可以拓展其它的了) 先看一下服務端程式的實現吧 Server.java import java.io.IOException;

Android簡單實現k線圖,

我並沒有根據股票的具體數字進行畫圖,如果大家需要具體實現的話,就需要根據具體的座標和股票值進行比例轉換,轉換好了以後就能進行具體畫圖                                       了,廢話不多說先上圖給大家看看   下面我就直接貼原始碼了 非常