LruCache类的使用(内存优化)

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

知识点:

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
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值