LruCache类的使用(内存优化)

来源:互联网 发布:网吧奖励软件 编辑:程序博客网 时间:2024/06/13 10:58

这样做,只能自己写图片加载工具类,完全抛弃了第三方的图片加载框架

知识点:

1)Runtime类(运行时类):Runtime类封装了运行时的环境,每个应用程序都有一个Runtime类实例,使应用程序能够与其运行的环境相连接。可以通过getRuntime 方法获取当前Runtime运行时对象的引用,旦得到了一个当前的Runtime对象的引用,就可以调用Runtime对象的方法去控制虚拟机的状态和行为。
Runtime.getRuntime().totalMemory()获取的值是动态的,是虚拟机从系统那里获取的,可以进行内存管理。

2)LruCache类:主要用于内存优化,核心是LinkedHashMap,用Lru算法+数据结构实现,把近期最少使用的数据从缓存中移除,保留使用最频繁的数据(近期最少使用的,使用频率)LruCache以键值对的形式存储数据。

主要用法:构造函数的使用,添加缓存,根据url获取缓存的方法

        //1)构造函数要传入一个int类型值,表示缓存的最大值,一般是虚拟机的几分之一。        int maxSize = (int) (Runtime.getRuntime().maxMemory() / 4);        LruCache<String, Bitmap> cacheMap = new LruCache(maxSize);        //2)添加缓存        cacheMap.put("key", bitmap);        //3)根据key获取缓存        Bitmap bit = cacheMap.get("key");

3)BitmapUtils和大多数图片加载框架一样,都是基于内存-文件-网络三级缓存。也就是加载图片的时候首先从内存缓存中取,如果没有再从文件缓存中取,如果文件缓存没有取到,就从网络下载图片并且加入内存和文件缓存。

BitmapUtils内存缓存是如何实现的?BitmapUtils内存缓存的核心类LruMemoryCache,LruMemoryCache代码和v4包的LruCache一样。

4)Executors线程池类的使用:ExecutorService executorService = Executors.newFixedThreadPool(5); 创建一个包含五个线程的线程池,主要是为了重复利用线程。ExecutorService是一个线程池的管理工具。


案例:在ListView中,使用LruCache缓存图片(去掉了sdcard缓存,相当于抄了一遍代码)

Activity中的代码:

package com.crs.demo.ui.lrucache;import android.graphics.Bitmap;import android.os.Bundle;import android.os.Handler;import android.support.v4.util.LruCache;import android.widget.ListView;import com.crs.demo.R;import com.crs.demo.adapter.LruCacheAdapter;import com.crs.demo.base.BaseActivity;import java.util.ArrayList;/** * Created on 2016/10/9. * Author:crs * Description:LruCache的使用 */public class LruCacheActivity extends BaseActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_lrucache);        initViews();    }    private void initViews() {        ArrayList list = new ArrayList<>();        list.add("http://img5.imgtn.bdimg.com/it/u=2296402476,2057547975&fm=21&gp=0.jpg");        list.add("http://img.sdchina.com/news/20100604/c01_2e9c516d-cf8e-468b-a9a5-bc78bc277e71_3.jpg");        list.add("http://p.ishowx.com/uploads/allimg/160823/415-160R3095959.jpg");        ListView lv_test_lru_cache = findView(R.id.lv_test_lru_cache);        LruCacheAdapter lruCacheAdapter = new LruCacheAdapter(this, list);        lv_test_lru_cache.setAdapter(lruCacheAdapter);    }}

adapter中的代码:

package com.crs.demo.adapter;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import com.crs.demo.R;import com.crs.demo.ui.lrucache.BitmapUtil;import java.util.ArrayList;/** * Created on 2016/10/9. * Author:crs * Description:LruCacheAdapter主要用于测试内存优化 */public class LruCacheAdapter extends BaseAdapter {    private LayoutInflater mInflater;    private ArrayList<String> list;    private final BitmapUtil mBitmapUtils;    public LruCacheAdapter(Context mContext, ArrayList<String> list) {        mInflater = LayoutInflater.from(mContext);        this.list = list;        mBitmapUtils = new BitmapUtil(mContext);    }    @Override    public int getCount() {        return list.size();    }    @Override    public Object getItem(int position) {        return null;    }    @Override    public long getItemId(int position) {        return 0;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {        View view = mInflater.inflate(R.layout.item_viewpager_lrucache, null);        ImageView iv = (ImageView) view.findViewById(R.id.iv_item_viewpager_lrucache);        mBitmapUtils.display(iv,list.get(position));        return view;    }}
BitmapUtil中的代码:

package com.crs.demo.ui.lrucache;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Handler;import android.os.Message;import android.support.v4.util.LruCache;import android.widget.ImageView;import com.crs.demo.utils.ToastUtils;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** * Created on 2016/10/9. * Author:crs * Description:封装LruCache的使用 */public class BitmapUtil {    private Context mContext;    private static final int SUCCESS_LOAD_DATA = 0;    private static final int FAILURE_LOAD_DATA = 1;    //LruCache实例,用于存储Bitmap    private LruCache<String, Bitmap> mLruCache;    //线程池管理类    private ExecutorService executorService = Executors.newFixedThreadPool(5);    //创建主线程的消息对象    private BitmapUtil.InnerHandler mHandler = new BitmapUtil.InnerHandler();    public BitmapUtil(Context context) {        this.mContext = context;        //总的可用内存        int mTotalSize = (int) Runtime.getRuntime().totalMemory();        mLruCache = new LruCache<String, Bitmap>(mTotalSize / 8) {            @Override            protected int sizeOf(String key, Bitmap value) {                return value.getRowBytes() * value.getHeight();            }        };    }    public void display(ImageView iv, String url) {        Bitmap bitmap = getBitmapFromMemory(url);        if (bitmap != null) {            iv.setImageBitmap(bitmap);        } else {            getBitmapFromInternet(iv, url);        }    }    private void getBitmapFromInternet(ImageView iv, String url) {        executorService.submit(new BitmapUtil.DownloadImageTask(iv, url));    }    private Bitmap getBitmapFromMemory(String url) {        return mLruCache.get(url);    }    //加载网络图片的线程类    private class DownloadImageTask implements Runnable {        private String imageUrl;        //如何把此ImageView对象传递到Handler中        private ImageView iv;        private HttpURLConnection conn;        public DownloadImageTask(ImageView iv, String url) {            this.imageUrl = url;            this.iv = iv;        }        @Override        public void run() {            try {                URL url = new URL(imageUrl);                conn = (HttpURLConnection) url.openConnection();                conn.setRequestMethod("GET");                conn.setConnectTimeout(3000);                if (conn.getResponseCode() == 200) {                    InputStream is = conn.getInputStream();                    //此时bitmap对象在子线程里面                    Bitmap bitmap = BitmapFactory.decodeStream(is);                    //使用LruCache执行内存缓存                    mLruCache.put(imageUrl, bitmap);                    //封装对象进行传递                    BitmapUtil.ImageViewBitmap imageViewBitmap = new BitmapUtil.ImageViewBitmap();                    imageViewBitmap.bitmap = bitmap;                    imageViewBitmap.iv = iv;                    Message message = mHandler.obtainMessage(SUCCESS_LOAD_DATA, imageViewBitmap);                    message.sendToTarget();                    is.close();                } else {                    mHandler.sendEmptyMessage(FAILURE_LOAD_DATA);                }            } catch (Exception e) {                e.printStackTrace();                mHandler.sendEmptyMessage(FAILURE_LOAD_DATA);            } finally {                if (conn != null) {                    conn.disconnect();                }            }        }    }    //传递消息的类    private class InnerHandler extends Handler {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            switch (msg.what) {                case SUCCESS_LOAD_DATA: {                    BitmapUtil.ImageViewBitmap imageViewBitmap = (BitmapUtil.ImageViewBitmap) msg.obj;                    Bitmap bitmap = imageViewBitmap.bitmap;                    ImageView iv = imageViewBitmap.iv;                    iv.setImageBitmap(bitmap);                }                break;                case FAILURE_LOAD_DATA: {                    ToastUtils.showShort(mContext, "图片加载异常");                }                break;            }        }    }    //把两者封装成一个对象进行传递    private static class ImageViewBitmap {        ImageView iv;        Bitmap bitmap;    }}

1 0