三级缓存机制

来源:互联网 发布:80和8080端口 编辑:程序博客网 时间:2024/05/02 04:40

本篇介绍Android中的三级缓存机制

参考网址:https://www.cnblogs.com/huangjie123/p/6130665.html

三级缓存指的是:内存缓存、本地缓存、网络缓存。

其各自的特点是内存缓存速度快, 优先读取,本地缓存速度其次, 内存没有,读本地,网络缓存速度最慢, 本地也没有,才访问网络。

对于网络缓存理解起来较为容易直接从网络中获取资源,本地缓存可以存在SD卡中,内存缓存一般存在数组或集合中。

下面我们从三部分来透析缓存机制

一、内存缓存

内存中读数据需要用到最近最少引用的算法(lrucache)。Lrucache算法要求为new LruCache<>() 传入一个分配给软件的最大内存,同时重写sizeof()方法,计算每一张图片的大小。

这样就可以直接调用LruCache的put()和get()方法。

二、本地缓存

当发现内存中没有数据时,找到SD卡中的存储文件。

通过Bitmap的compress()方法向文件夹中写数据,通过位图工厂BitmapFactory的decodeStream()读取数据,同时可以为decodeStream()方法传入options参数,缩小图片。

三、网络缓存

本地仍然没有获取数据,再从网络获取。

网络获取数据可以用异步任务来执行(耗时操作不能再主线程中执行)。

异步任务需要重写onPostExecute()方法和doInBackground()方法。

doInBackground()方法中访问网路,这里用到的是Httpurlconnection,通过连接得到输入流,利用位图工厂转换成位图,返回。onPostExecute()方法在doInBackground()方法执行后执行,传入的参数数doInBackground()方法的返回值。

代码调用和缓存工具类如下:

public class NextActivity extends AppCompatActivity{    private ImageView iv;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_next);        getBitmap();    }    private void getBitmap() {        iv = (ImageView) findViewById(R.id.iv_next);        CacheUtils utils = new CacheUtils();        utils.display(iv,"http://a.hiphotos.baidu.com/image/pic/item/a9d3fd1f4134970a489111e59ccad1c8a6865d1d.jpg");    }}

布局就是一个ImageView,此处省略布局了。

下面我们看缓存工具类:

1、总工具类

import android.graphics.Bitmap;import android.widget.ImageView;import com.dota.musicapp.utils.L;/** * 三级缓存的管理工具类 * Created by ${Dota.Wang} on 2017/11/25. */public class CacheUtils {    private MemoryCacheUtils mMemoryCacheUtils;    private LocalCacheUtils mLocalCacheUtils;    private NetCacheUtils mNetCacheUtils;    public CacheUtils() {        mMemoryCacheUtils = new MemoryCacheUtils();        mLocalCacheUtils = new LocalCacheUtils();        mNetCacheUtils = new NetCacheUtils(mMemoryCacheUtils, mLocalCacheUtils);    }    public void display(ImageView imageView, String url) {        //内存缓存   生命周期同调用者        Bitmap bitmap = mMemoryCacheUtils.getBitmapToMemory(url);        if (bitmap != null) {            imageView.setImageBitmap(bitmap);            L.i( "diaplay: 221111111111");            return;        }        //本地缓存        bitmap = LocalCacheUtils.getBitmapToLoacl(url);        if (bitmap != null) {            L.i( "diaplay: 1111111");            imageView.setImageBitmap(bitmap);            mMemoryCacheUtils.putBitmapToMemory(bitmap, url);            return;        }        //网络缓存        mNetCacheUtils.getBitmapFromNet(imageView, url);    }}

2、内存缓存工具类

import android.graphics.Bitmap;import android.util.LruCache;import com.dota.musicapp.utils.L;/** * 第一级缓存:内存缓存的工具类 * Created by ${Dota.Wang} on 2017/11/25. */public class MemoryCacheUtils {    private LruCache<String, Bitmap> mMemoryCache;    public MemoryCacheUtils() {        int maxmemory = (int) Runtime.getRuntime().maxMemory();        L.i("MemoryCacheUtils: " + maxmemory);        mMemoryCache = new LruCache<String, Bitmap>(maxmemory / 8) {            @Override            protected int sizeOf(String key, Bitmap value) {                return value.getRowBytes() * value.getHeight();            }        };    }    public void putBitmapToMemory(Bitmap bitmap, String url) {        L.i( "putBitmapToMemory: ");        mMemoryCache.put(url, bitmap);    }    public Bitmap getBitmapToMemory(String url) {        L.i("getBitmapToMemory: ");        Bitmap bitmap = mMemoryCache.get(url);        return bitmap;    }}

3、本地缓存工具类

import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Environment;import com.dota.musicapp.utils.L;import com.dota.musicapp.utils.Md5Utils;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;/** * 第二级缓存:本地缓存(SD卡)的工具类 * Created by ${Dota.Wang} on 2017/11/25. */public class LocalCacheUtils {    public static void putBitmapToLoacl(Bitmap bitmap, String url) {        String encode = Md5Utils.encode(url);        File file = new File(Environment.getExternalStorageDirectory(), encode);        L.i("putBitmapToLoacl: " + file.toString());        File parent = file.getParentFile();        if (!parent.exists()) {            parent.mkdirs();        }        try {            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(file));        } catch (FileNotFoundException e) {            e.printStackTrace();        }    }    public static Bitmap getBitmapToLoacl(String url) {        String encode = Md5Utils.encode(url);        File file = new File(Environment.getExternalStorageDirectory(), encode);        if (file.exists()) {            BitmapFactory.Options opts = new BitmapFactory.Options();            opts.inSampleSize = 3;            try {                Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file), null, opts);                return bitmap;            } catch (FileNotFoundException e) {                e.printStackTrace();                return null;            }        }        return null;    }}

4、网络缓存工具类

import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.AsyncTask;import android.widget.ImageView;import java.io.IOException;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;/** * 第三级缓存:网络缓存的工具类 * Created by ${Dota.Wang} on 2017/11/25. */public class NetCacheUtils {    private MemoryCacheUtils mMemoryCacheUtils;    private LocalCacheUtils mLocalCacheUtils;    public NetCacheUtils(MemoryCacheUtils mMemoryCacheUtils, LocalCacheUtils mLocalCacheUtils) {        this.mLocalCacheUtils = mLocalCacheUtils;        this.mMemoryCacheUtils = mMemoryCacheUtils;    }    public void getBitmapFromNet(ImageView imageView, String url) {        imageView.setTag(url);        Bitmaptask task = new Bitmaptask();        task.execute(imageView, url);    }    class Bitmaptask extends AsyncTask<Object, Void, Bitmap> {        private HttpURLConnection urlConnection;        private ImageView imageView;        private String url;        @Override        protected void onPostExecute(Bitmap bitmap) {            if (bitmap != null) {                if (url.equals(imageView.getTag())) {                    imageView.setImageBitmap(bitmap);                    System.out.print("onPostExecute");                    mLocalCacheUtils.putBitmapToLoacl(bitmap, url);                    mMemoryCacheUtils.putBitmapToMemory(bitmap, url);                }            }        }        @Override        protected Bitmap doInBackground(Object[] params) {            imageView = (ImageView) params[0];            url = (String) params[1];            Bitmap bitmap = downloadFromNet(url);            return bitmap;        }        private Bitmap downloadFromNet(String url) {            try {                urlConnection = (HttpURLConnection) new URL(url).openConnection();                urlConnection.setConnectTimeout(5000);                urlConnection.setRequestMethod("GET");                int responseCode = urlConnection.getResponseCode();                if (responseCode == 200) {                    InputStream inputStream = urlConnection.getInputStream();                    BitmapFactory.Options opts = new BitmapFactory.Options();                    opts.inSampleSize = 2;                    Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, opts);                    return bitmap;                }            } catch (IOException e) {                e.printStackTrace();                return null;            } finally {                urlConnection.disconnect();            }            return null;        }    }}

5、本地缓存中用到的Md5Utils工具类

import java.security.MessageDigest;/** * Created by ${Dota.Wang} on 2017/11/25. */public class Md5Utils {    public static String encode(String pwd) {        try {            MessageDigest digest = MessageDigest.getInstance("md5");            byte[] bs = digest.digest(pwd.getBytes());            StringBuilder sb = new StringBuilder();            for (byte b : bs) {                int number = b & 0xff;                String str = Integer.toHexString(number);                if (str.length() == 1) {                    sb.append("0");                }                sb.append(number);            }            return sb.toString();        } catch (Exception e) {            e.printStackTrace();            return null;        }    }}

6、最后,注意注册表中对权限的添加

<uses-permission android:name="android.permission.INTERNET" />    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
原创粉丝点击