最后,简单粗暴的一句话概括:**
**Picasso所能实现的功能,Glide都能做,无非是所需的设置不同。但是Picasso体积比起Glide小太多如果项目中网络请求本身用的就是okhttp或者retrofit(本质还是okhttp),那么建议用Picasso,体积会小很多(Square全家桶的干活)。
Glide的好处是大型的图片流,比如gif、Video,如果你们是做美拍、爱拍这种视频类应用,建议使用。
Fresco在5.0以下的内存优化非常好,代价就是体积也非常的大,按体积算Fresco>Glide>Picasso不过在使用起来也有些不便(小建议:他只能用内置的一个ImageView来实现这些功能,用起来比较麻烦,我们通常是根据Fresco自己改改,直接使用他的Bitmap层)
**
下面具体讲解图片三级缓存是哪三级?(Picasso 和 Glide 和 Fresco 基本也是这 三级)
原文:https://www.cnblogs.com/RabbitLx/p/5792268.html
我们不能每次加载图片的时候都让用户从网络上下载,这样不仅浪费流量又会影响用户体验,所以Android中引入了图片的缓存这一操作机制。
原理:
首先根据图片的网络地址在网络上下载图片,将图片先缓存到内存缓存中,缓存到强引用中 也就是LruCache中。
如果强引用中空间不足,就会将较早存储的图片对象驱逐到软引用(softReference)中存储,然后将图片缓存到文件(内部存储外部存储)中;读取图片的时候,先读取内存缓存,判断强引用中是否存在图片,如果强引用中存在,则直接读取
如果强引用中不存在,则判断软引用中是否存在,如果软引用中存在,则将软引用中的图片添加到强引用中并且删除软引用中的数据
如果软引用中不存在,则读取文件存储,如果文件存储不存在,则网络加载。
下载: 网络–内存–文件
读取: 内存–强引用–软引用–文件–网络
也就是这样的一个过程,下面用一个简单地demo来演示一下图片你的三级缓存,此demo中只有一个界面,界面上一个ImageView用来显示图片,一个按钮用来点击的时候加载图片。布局如下:
1 <?xml version="1.0" encoding="utf-8"?>
2 <RelativeLayout xmlns:android\="http://schemas.android.com/apk/res/android"
3 android:layout\_width\="match\_parent"
4 android:layout\_height\="match\_parent"
5 \>
6 <ImageView
7 android:id\="@+id/iv\_img"
8 android:layout\_width\="wrap\_content"
9 android:layout\_height\="wrap\_content"
10 android:src\="@mipmap/ic\_launcher"
11 android:layout\_centerInParent\="true"/>
12 <Button
13 android:id\="@+id/btn\_download"
14 android:layout\_below\="@+id/iv\_img"
15 android:layout\_centerHorizontal\="true"
16 android:layout\_width\="wrap\_content"
17 android:layout\_height\="wrap\_content"
18 android:text\="加载图片"/>
19
20 </RelativeLayout\>
因为要从网络下载数据,还要存储到本地sd卡中,所以不要忘了为程序添加网络访问的权限、网络状态访问的权限和向外部存储设备写内容的权限:
1 <uses-permission android:name="android.permission.INTERNET" />
2 <uses-permission android:name="android.permission.ACCESS\_NETWORK\_STATE" />
3 <uses-permission android:name="android.permission.WRITE\_EXTERNAL\_STORAGE" />
接着,创建一个 HttpUtils 工具类用于访问网络,代码如下:
1 package com.yztc.lx.cashimg; 2
3 import android.content.Context; 4 import android.net.ConnectivityManager; 5 import android.net.NetworkInfo; 6
7 import java.io.ByteArrayOutputStream; 8 import java.io.IOException; 9 import java.io.InputStream;
10 import java.net.HttpURLConnection;
11 import java.net.URL;
12
13 /\*\*网络访问工具类
14 \* Created by Lx on 2016/8/19.
15 \*/
16
17 public class HttpUtils {
18 /\*\*
19 \* 判断网络连接是否通畅
20 \* @param mContext
21 \* @return
22 \*/
23 public static boolean isNetConn(Context mContext) {
24 ConnectivityManager manager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY\_SERVICE);
25 NetworkInfo info = manager.getActiveNetworkInfo();
26 if (info != null) {
27 return info.isConnected();
28 } else {
29 return false;
30 }
31 }
32
33 /\*\*
34 \* 根据path下载网络上的数据
35 \* @param path 路径
36 \* @return 返回下载内容的byte数据形式
37 \*/
38 public static byte\[\] getDateFromNet(String path) {
39 ByteArrayOutputStream baos = new ByteArrayOutputStream();
40 try {
41 URL url = new URL(path);
42 HttpURLConnection conn = (HttpURLConnection) url.openConnection();
43 conn.setRequestMethod("GET");
44 conn.setConnectTimeout(5000);
45 conn.setDoInput(true);
46 conn.connect();
47 if (conn.getResponseCode()==200) {
48 InputStream is = conn.getInputStream();
49 byte b\[\] = new byte\[1024\];
50 int len;
51 while ((len=is.read(b))!=-1) {
52 baos.write(b, 0, len);
53 }
54 return baos.toByteArray();
55 }
56 } catch (IOException e) {
57 e.printStackTrace();
58 }
59 return baos.toByteArray();
60 }
61
62 }
还有操作外部存储的工具类:
1 package com.yztc.lx.cashimg; 2
3 import android.graphics.Bitmap; 4 import android.graphics.BitmapFactory; 5 import android.os.Environment; 6
7 import java.io.ByteArrayOutputStream; 8 import java.io.File; 9 import java.io.FileInputStream;
10 import java.io.FileOutputStream;
11 import java.io.IOException;
12
13 /\*\*
14 \* Created by Lx on 2016/8/20.
15 \*/
16
17 public class ExternalStorageUtils {
18 /\*\*
19 \* 将传递过来的图片byte数组存储到sd卡中
20 \* @param imgName 图片的名字
21 \* @param buff byte数组
22 \* @return 返回是否存储成功
23 \*/
24 public static boolean storeToSDRoot(String imgName, byte buff\[\]) {
25 boolean b = false;
26 String basePath = Environment.getExternalStorageDirectory().getAbsolutePath();
27 File file = new File(basePath, imgName);
28 try {
29 FileOutputStream fos = new FileOutputStream(file);
30 fos.write(buff);
31 fos.close();
32 b = true;
33 } catch (IOException e) {
34 e.printStackTrace();
35 }
36 return b;
37 }
38
39 /\*\*
40 \* 从本地内存中根据图片名字获取图片
41 \* @param imgName 图片名字
42 \* @return 返回图片的Bitmap格式
43 \*/
44 public static Bitmap getImgFromSDRoot(String imgName) {
45 Bitmap bitmap = null;
46 String basePath = Environment.getExternalStorageDirectory().getAbsolutePath();
47 File file = new File(basePath, imgName);
48 try {
49 FileInputStream fis = new FileInputStream(file);
50 ByteArrayOutputStream baos = new ByteArrayOutputStream();
51 byte b\[\] = new byte\[1024\];
52 int len;
53 while ((len = fis.read(b)) != -1) {
54 baos.write(b, 0, len);
55 }
56 byte buff\[\] = baos.toByteArray();
57 if (buff != null && buff.length != 0) {
58 bitmap = BitmapFactory.decodeByteArray(buff, 0, buff.length);
59 }
60 } catch (IOException e) {
61 e.printStackTrace();
62 }
63 return bitmap;
64 }
65
66
67 }
本例中将图片默认存在了sd卡根目录中。
然后是最主要的主函数了:
1 package com.yztc.lx.cashimg; 2
3 import android.graphics.Bitmap; 4 import android.graphics.BitmapFactory; 5 import android.os.Bundle; 6 import android.os.Handler; 7 import android.os.Message; 8 import android.support.v7.app.AppCompatActivity; 9 import android.util.Log; 10 import android.util.LruCache; 11 import android.view.View; 12 import android.widget.Button; 13 import android.widget.ImageView; 14 import android.widget.Toast; 15
16 import java.lang.ref.SoftReference; 17 import java.util.LinkedHashMap; 18
19 public class MainActivity extends AppCompatActivity implements View.OnClickListener { 20
21 private Button btn\_download; 22 private ImageView iv\_img; 23 private MyLruCache myLruCache; 24 private LinkedHashMap<String, SoftReference<Bitmap>> cashMap = new LinkedHashMap<>();
25 private static final String TAG = "MainActivity";
26 private String imgPath = "http://www.3dmgame.com/UploadFiles/201212/Medium\_20121217143424221.jpg";
27 private Handler handler = new Handler() { 28 @Override
29 public void handleMessage(Message msg) { 30 Bitmap bitmap = (Bitmap) msg.obj; 31 iv\_img.setImageBitmap(bitmap);
32 Toast.makeText(MainActivity.this, "从网络上下载图片", Toast.LENGTH\_SHORT).show();
33 }
34 };
35
36 @Override
37 protected void onCreate(Bundle savedInstanceState) { 38 super.onCreate(savedInstanceState);
39 setContentView(R.layout.activity\_main);
40 initView();
41 int totalMemory = (int) Runtime.getRuntime().maxMemory();
42 int size = totalMemory / 8;
43 myLruCache = new MyLruCache(size); 44 btn\_download.setOnClickListener(this);
45 }
46
47 private void initView() { 48 btn\_download = (Button) findViewById(R.id.btn\_download); 49 iv\_img = (ImageView) findViewById(R.id.iv\_img); 50 }
51
52 @Override
53 public void onClick(View v) { 54 Bitmap b = getImgCache(); 55 if (b != null) {
56 iv\_img.setImageBitmap(b);
57 } else { 58 new Thread(new Runnable() { 59 @Override
60 public void run() { 61 if (HttpUtils.isNetConn(MainActivity.this)) {
62 byte b\[\] = HttpUtils.getDateFromNet(imgPath); 63 if (b != null && b.length != 0) {
64 Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, b.length);
65 Message msg = Message.obtain(); 66 msg.obj = bitmap; 67 handler.sendMessage(msg);
68 myLruCache.put(imgPath, bitmap);
69 Log.d(TAG, "run: " + "缓存到强引用中成功");
70 boolean bl = ExternalStorageUtils.storeToSDRoot("haha.jpg", b);
71 if (bl) { 72 Log.d(TAG, "run: " + "缓存到本地内存成功");
73 } else { 74 Log.d(TAG, "run: " + "缓存到本地内存失败");
75 }
76 } else { 77 Toast.makeText(MainActivity.this, "下载失败!", Toast.LENGTH\_SHORT).show();
78 }
79
80 } else { 81 Toast.makeText(MainActivity.this, "请检查你的网络!", Toast.LENGTH\_SHORT).show();
82 }
83 }
84 }).start();
85 }
86 }
87
88 /\*\*
89 \* 从缓存中获取图片
90 \*
91 \* @return 返回获取到的Bitmap 92 \*/
93 public Bitmap getImgCache() { 94 Bitmap bitmap = myLruCache.get(imgPath); 95 if (bitmap != null) {
96 Log.d(TAG, "getImgCache: " + "从LruCache获取图片");
97 } else { 98 SoftReference<Bitmap> sr = cashMap.get(imgPath); 99 if (sr != null) {
100 bitmap = sr.get();
101 myLruCache.put(imgPath, bitmap);
102 cashMap.remove(imgPath);
103 Log.d(TAG, "getImgCache: " + "从软引用获取图片");
104 } else {
105 bitmap = ExternalStorageUtils.getImgFromSDRoot("haha.jpg");
106 Log.d(TAG, "getImgCache: " + "从外部存储获取图片");
107 }
108 }
109 return bitmap;
110 }
111
112 /\*\*
113 \* 自定义一个方法继承系统的LruCache方法
114 \*/
ence<Bitmap> sr = cashMap.get(imgPath); 99 if (sr != null) {
100 bitmap = sr.get();
101 myLruCache.put(imgPath, bitmap);
102 cashMap.remove(imgPath);
103 Log.d(TAG, "getImgCache: " + "从软引用获取图片");
104 } else {
105 bitmap = ExternalStorageUtils.getImgFromSDRoot("haha.jpg");
106 Log.d(TAG, "getImgCache: " + "从外部存储获取图片");
107 }
108 }
109 return bitmap;
110 }
111
112 /\*\*
113 \* 自定义一个方法继承系统的LruCache方法
114 \*/