Android学习之路-------复习一下缓存和读取缓存,网络加载图片
来源:互联网 发布:大数据涂子沛概括 编辑:程序博客网 时间:2024/06/05 15:33
在开发中,遇到很多大量图片呈现给用户,那么我们怎么又快又高效的显示给用户呢?
在这里结合前人写的文章和自己的一些改动。
一般我们写的过程中是这么处理的:先去缓存(WeakHashMap<String, Bitmap>来存储图片)中提取,这样速度快又节约流量,缓存中没有再选择本地有图片没有,如果两者都没有则只有从网络去获取。
我们先分开讲解
方法一:网络下载
方法二:从本地文件加载
方法三:从缓存中读取
先来说方法一:
加载很多图片的时候,我们经常用多线程在后台下载,在handler中将图片呈现在界面。
直接上代码
[java] view plain copy
- //网络获取图片
- protected Bitmap getNetBitmapByURL(String urlString) {
- URL url = null;
- InputStream inputStream = null;
- HttpURLConnection urlConnection = null;
- Bitmap bmp = null;
- try {
- url = new URL(urlString);
- urlConnection = (HttpURLConnection) url.openConnection();
- urlConnection.setRequestMethod("GET");
- urlConnection.setConnectTimeout(10000);
- inputStream = urlConnection.getInputStream();
- byte[] bt = getBytesFromStream(inputStream);
- bmp = BitmapFactory.decodeByteArray(bt, 0, bt.length);
- } catch (MalformedURLException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- if (null != inputStream) {
- try {
- inputStream.close();
- inputStream = null;
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- if (null != urlConnection) {
- urlConnection.disconnect();
- urlConnection = null;
- }
- }
- return bmp;
- }
- // 数据流
- private byte[] getBytesFromStream(InputStream inputStream) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- byte[] b = new byte[1024];
- int len = 0;
- while (len != -1) {
- try {
- len = inputStream.read(b);
- } catch (IOException e) {
- e.printStackTrace();
- }
- if (len != -1) {
- baos.write(b, 0, len);
- }
- }
- if (inputStream != null) {
- try {
- inputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return baos.toByteArray();
- }
再来说方法二本地获取:
直接根据图片路径获取Bitmap
[java] view plain copy
- private boolean cacheBmpToMemory(File file) {
- boolean sucessed = true;
- InputStream inputStream = null;
- try {
- inputStream = new FileInputStream(file);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- sucessed = false;
- }
- byte[] bs = getBytesFromStream(inputStream);
- Bitmap bitmap = BitmapFactory.decodeByteArray(bs, 0, bs.length);
- if (bitmap == null) {
- return null;
- }
- return bitmap;
- }
- private byte[] getBytesFromStream(InputStream inputStream) {
- boolean b2 = true;
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- byte[] b = new byte[1024];
- int len = 0;
- while (len != -1 && b2) {
- try {
- len = inputStream.read(b);
- if (len != -1) {
- baos.write(b, 0, len);
- }
- } catch (IOException e) {
- b2 = false;
- try {
- inputStream.close();
- } catch (IOException e1) {
- }
- }
- }
- if (inputStream != null) {
- try {
- inputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return baos.toByteArray();
- }
方法三缓存获取:
用弱引用:WeakHashMap<String, Bitmap>,以弱键 实现的基于哈希表的 Map,在 WeakHashMap 中,当某个键不再正常使用时,将自动移除其条目。更精确地说,对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收。丢弃某个键时,其条目从映射中有效地移除。
WeakHashMap 中的每个键对象间接地存储为一个弱引用的指示对象。因此,不管是在映射内还是在映射之外,只有在垃圾回收器清除某个键的弱引用之后,该键才会自动移除
这个地方结合方法一和方法二,写了一个有关图片缓存的解决方法。
Java文件:
ImageCache.java
[java] view plain copy
- package com.imageService;
- import java.io.ByteArrayOutputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.util.WeakHashMap;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.Bitmap.CompressFormat;
- import android.os.Environment;
- public class ImageCache extends WeakHashMap<String, Bitmap> {
- private static ImageCache mNetImageViewCache = new ImageCache();
- private static final String CACHE_FILE = "/Cache";
- private ImageCache() {
- }
- public static ImageCache getInstance() {
- return mNetImageViewCache;
- }
- /**
- * 判断图片是否存在首先判断内存中是否存在然后判断本地是否存在
- *
- * @param url
- * @return
- */
- public boolean isBitmapExit(String url) {
- boolean isExit = containsKey(url);
- if (false == isExit) {
- isExit = isLocalHasBmp(url);
- }
- return isExit;
- }
- /*
- * 判断本地有没有
- */
- private boolean isLocalHasBmp(String url) {
- boolean isExit = true;
- String name = changeUrlToName(url);
- String filePath = isCacheFileIsExit();
- File file = new File(filePath, name);
- if (file.exists()) {
- isExit = cacheBmpToMemory(file, url);
- } else {
- isExit = false;
- }
- return isExit;
- }
- /*
- * 将本地图片缓存到内存中
- */
- private boolean cacheBmpToMemory(File file, String url) {
- boolean sucessed = true;
- InputStream inputStream = null;
- try {
- inputStream = new FileInputStream(file);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- sucessed = false;
- }
- byte[] bs = getBytesFromStream(inputStream);
- Bitmap bitmap = BitmapFactory.decodeByteArray(bs, 0, bs.length);
- if (bitmap == null) {
- return false;
- }
- this.put(url, bitmap, false);
- return sucessed;
- }
- private byte[] getBytesFromStream(InputStream inputStream) {
- boolean b2 = true;
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- byte[] b = new byte[1024];
- int len = 0;
- while (len != -1 && b2) {
- try {
- len = inputStream.read(b);
- if (len != -1) {
- baos.write(b, 0, len);
- }
- } catch (IOException e) {
- b2 = false;
- try {
- inputStream.close();
- } catch (IOException e1) {
- }
- }
- }
- if (inputStream != null) {
- try {
- inputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return baos.toByteArray();
- }
- /*
- * 判断缓存文件夹是否存在如果存在怎返回文件夹路径,如果不存在新建文件夹并返回文件夹路径
- */
- private String isCacheFileIsExit() {
- String filePath = "";
- String rootpath = "";
- if (Environment.getExternalStorageState().equals(
- Environment.MEDIA_MOUNTED)) {
- rootpath = Environment.getExternalStorageDirectory().toString();
- }
- filePath = rootpath + CACHE_FILE;
- File file = new File(filePath);
- if (!file.exists()) {
- file.mkdirs();
- }
- return filePath;
- }
- /*
- * 将url变成图片的地址
- */
- private String changeUrlToName(String url) {
- String name = url.replaceAll(":", "_");
- name = name.replaceAll("//", "_");
- name = name.replaceAll("/", "_");
- name = name.replaceAll("=", "_");
- name = name.replaceAll(",", "_");
- name = name.replaceAll("&", "_");
- return name;
- }
- public Bitmap put(String key, Bitmap value) {
- String filePath = isCacheFileIsExit();
- String name = changeUrlToName(key);
- File file = new File(filePath, name);
- OutputStream outputStream = null;
- try {
- outputStream = new FileOutputStream(file);
- value.compress(CompressFormat.JPEG, 100, outputStream);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
- try {
- if (null != outputStream)
- outputStream.flush();
- } catch (IOException e1) {
- e1.printStackTrace();
- }
- try {
- if (null != outputStream)
- outputStream.flush();
- } catch (IOException e) {
- e.printStackTrace();
- }
- if (null != outputStream) {
- try {
- outputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- outputStream = null;
- }
- return super.put(key, value);
- }
- /**
- *
- * @param key
- * @param value
- * @param isCacheToLocal
- * 是否缓存到本地
- * @return
- */
- public Bitmap put(String key, Bitmap value, boolean isCacheToLocal) {
- if (isCacheToLocal) {
- return this.put(key, value);
- } else {
- return super.put(key, value);
- }
- }
- }
ImageService.java
[java] view plain copy
- package com.imageService;
- import java.io.ByteArrayOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.lang.ref.SoftReference;
- import java.net.HttpURLConnection;
- import java.net.MalformedURLException;
- import java.net.URL;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.os.Handler;
- import android.os.Message;
- import android.util.Log;
- import android.widget.ImageView;
- /**
- * @author jingche.yhq
- 使用说明:
- 1.先增加权限:
- <uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- 2.图片URL和ImageView直接输入函数
- EX:
- ImageService imageService = new ImageService(this);
- ImageView imageView;
- imageService.setBitmapByURL2("http://i1.itc.cn/20120801/a75_b0e447db_3573_ab5c_2058_5845d13545b9_1.jpg", imageView,defaultBitmap);
- */
- public class ImageService {
- //*********************************************线程池获取图片资源******************************************************
- //本地数据缓存
- public Map<String, SoftReference<Bitmap>> imageCacheMap = new HashMap<String, SoftReference<Bitmap>>();
- //固定五个线程来执行任务
- private ExecutorService executorService = Executors.newFixedThreadPool(5);
- //回调函数使用
- final static ImageService imageService = new ImageService();
- public static ImageService getInstance(){
- return imageService;
- }
- /**
- * 将图片放进缓存,图片名称是由URL去掉一些符号得到
- *
- * @param url
- * 地址
- * @param bitmap
- * 图片
- */
- public void putImageCache(String url, Bitmap bitmap) {
- try {
- if(!ImageCache.getInstance().isBitmapExit(url));
- ImageCache.getInstance().put(url, bitmap, true);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- /**
- *
- * @param url图片URL
- *
- * @param imageView imageView
- *
- * @param defaultBitmap 获取图片失败这显示默认图片
- */
- public void setBitmapByURL(String url,final ImageView imageView,final Bitmap defaultBitmap,boolean isCacheToLocal) {
- //采用Handler+Thread+封装外部接口
- //如果缓存过就会从缓存中取出图像,ImageCallback接口中方法也不会被执行
- Bitmap cacheImage = loadBitmap(url,imageView,isCacheToLocal,new ImageCallback() {
- //请参见实现:如果第一次加载URL时下面方法会执行
- @Override
- public void imageLoad(ImageView imageView, Bitmap bitmap) {
- //如果返回的Bitmap为空这选择默认图片
- if (bitmap!=null) {
- imageView.setImageBitmap(bitmap);
- }else {
- imageView.setImageBitmap(defaultBitmap);
- }
- }
- });
- if(cacheImage!=null){
- imageView.setImageBitmap(cacheImage);
- }else {
- // imageView.setImageBitmap(defaultBitmap);
- }
- }
- /**
- *
- * @param imageUrl 图像URL地址
- * @param imageCallback 回调接口
- * @return 返回内存中缓存的图像,第一次加载返回null
- */
- public Bitmap loadBitmap(final String imageUrl,final ImageView imageView,final boolean isCacheToLocal,final ImageCallback imageCallback) {
- //如果缓存过就从缓存中取出数据
- final Handler handler = new Handler()
- {
- @Override
- public void handleMessage(Message msg)
- {
- imageCallback.imageLoad(imageView, (Bitmap)msg.obj);
- }
- };
- if (imageCacheMap.containsKey(imageUrl)) {
- Log.e("提示", "缓存获取图片");
- SoftReference<Bitmap> softReference = imageCacheMap.get(imageUrl);
- if (softReference.get() != null) {
- return softReference.get();
- }
- }else
- if(ImageCache.getInstance().isBitmapExit(imageUrl)){
- Log.e("提示", "本地获取图片");
- Bitmap bitmap=null;
- try {
- bitmap = ImageCache.getInstance().get(imageUrl);
- } catch (Exception e) {
- bitmap = null;
- }
- return bitmap;
- }
- else {
- //缓存中没有图像,则从网络上取出数据,并将取出的数据缓存到内存中
- executorService.submit(new Runnable() {
- public void run() {
- try {
- //获取图片
- final Bitmap bitmap = getNetBitmapByURL(imageUrl);
- //将图片放置到内存中
- Log.e("提示", "网络获取图片"+Thread.currentThread().getName());
- if(bitmap!=null){
- Log.e("提示", "存储图");
- imageCacheMap.put(imageUrl, new SoftReference<Bitmap>(bitmap));
- ImageCache.getInstance().put(imageUrl, bitmap, isCacheToLocal);
- }
- Message msg = handler.obtainMessage(0, bitmap);
- handler.sendMessage(msg);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- });
- }
- return null;
- }
- //网络获取图片
- protected Bitmap getNetBitmapByURL(String urlString) {
- URL url = null;
- InputStream inputStream = null;
- HttpURLConnection urlConnection = null;
- Bitmap bmp = null;
- try {
- url = new URL(urlString);
- urlConnection = (HttpURLConnection) url.openConnection();
- urlConnection.setRequestMethod("GET");
- urlConnection.setConnectTimeout(10000);
- inputStream = urlConnection.getInputStream();
- byte[] bt = getBytesFromStream(inputStream);
- bmp = BitmapFactory.decodeByteArray(bt, 0, bt.length);
- } catch (MalformedURLException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- if (null != inputStream) {
- try {
- inputStream.close();
- inputStream = null;
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- if (null != urlConnection) {
- urlConnection.disconnect();
- urlConnection = null;
- }
- }
- return bmp;
- }
- // 数据流
- private byte[] getBytesFromStream(InputStream inputStream) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- byte[] b = new byte[1024];
- int len = 0;
- while (len != -1) {
- try {
- len = inputStream.read(b);
- } catch (IOException e) {
- e.printStackTrace();
- }
- if (len != -1) {
- baos.write(b, 0, len);
- }
- }
- if (inputStream != null) {
- try {
- inputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return baos.toByteArray();
- }
- //对外界开放的回调接口
- private interface ImageCallback {
- //注意 此方法是用来设置目标对象的图像资源
- public void imageLoad(ImageView imageView, Bitmap bitmap);
- }
- }
test
[java] view plain copy
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- ImageService imageService = new ImageService();
- ImageView imageView = (ImageView)findViewById(R.id.imageView1);
- imageService.setBitmapByURL("http://i1.itc.cn/20120801/a75_b0e447db_3573_ab5c_2058_5845d13545b9_1.jpg", imageView,BitmapFactory.decodeResource(getResources(), R.drawable.icon));
- }
0 0
- Android学习之路-------复习一下缓存和读取缓存,网络加载图片
- Android加载网络图片学习过程,涉及到本地缓存
- Android之缓存网络图片
- Android之ListView异步加载网络图片(优化缓存机制)
- Android之ListView异步加载网络图片(优化缓存机制) .
- Android之ListView异步加载网络图片(优化缓存机制)
- Android之ListView异步加载网络图片(优化缓存机制)
- Android之ListView异步加载网络图片(优化缓存机制)
- Android之ListView异步加载网络图片(优化缓存机制)
- Android之ListView异步加载网络图片(优化缓存机制)
- Android之ListView异步加载网络图片(优化缓存机制)
- Android之ListView异步加载网络图片(优化缓存机制)
- Android之ListView异步加载网络图片(优化缓存机制)
- Android之ListView异步加载网络图片(优化缓存机制)
- Android之ListView异步加载网络图片(优化缓存机制)
- Android网络图片加载详解之"三级缓存"
- android从本地缓存和网络加载图片
- 网络加载图片缓存
- 采样之MCMC
- Web上传文件的安全方式
- 三大 JS 框架的较量:Angular.js 与 React.js 与 Ember.js
- c++输入输出流操作笔记
- Codeforces#378 div.2 C. Epidemic in Monstropolis
- Android学习之路-------复习一下缓存和读取缓存,网络加载图片
- poj_3974最长回文子序列基础题
- 详细解释Basic disk和Dynamic disk
- 数据结构实验之数组二:稀疏矩阵
- Android颜色大全
- u-boot-2016.09移植(3)-u-boot-spl.bin
- PAT_乙级 1001 害死人不偿命的(3n+1)猜想
- Node.js学习笔记_模块调用
- UVA 10125 Sumsets .