開源框架之[-Picasso-]應用篇
零、前言
Picasso是一個圖片載入的框架,內部依賴了OkHttp,OkHttp內部依賴了okio
依賴: implementation 'com.squareup.picasso:picasso:2.71828'
本篇講一下Picasso的用法,下一篇分析一下Picasso的原始碼

picasso.png
一、Picasso的快取相關
Picasso.get().setIndicatorsEnabled(true); |--標記處圖片載入的位置 |--紅色,網路載入 |--綠色,記憶體載入 |--藍色,磁碟載入
1.點選時進行網路載入
可見是紅色,網路載入
String url = "http://192.168.43.60:8080/imgs/HXqqASHJETSlvpnc.jpg"; imageView.setOnClickListener(v -> { Picasso.get().load(url) .into(imageView); });

網路載入.png
2.再次點選載入網路圖片
可見是綠色,記憶體載入。這時並未去請求網路載入圖片,直接用記憶體中的快取圖片

記憶體載入.png
3.退出再進來載入網路圖片
可見是藍色,即從磁碟讀取的本地檔案

磁碟載入.png
從快取來看標準的DiskLruCache
|---檔名:鍵的md5值 |---XXXXX.0 檔案:請求資訊 |---XXXXX.1 檔案:響應資料(這裡即是圖片) |---journal 檔案:使用日誌 |---檔案大小: 從伺服器端的資源來看,並未壓縮

快取.png

伺服器端.png
5.小結一下:
記憶體快取-->本地磁碟快取-->網路快取(即資源)

三級快取.png
二、快取策略
1.做個試驗
貌似完美無缺,但是...圖片的更新是個問題
現在將服務端的圖片更新一下:發現現在客戶端是無法更新的
也就是快取會妨礙獲取更新後的圖片,必須清除快取才能更新,所以凡事有利必有弊

更新圖片.png

客戶端更新圖片.png
2.網路策略: NetworkPolicy
與記憶體策略 MemoryPolicy
比如下拉重新整理的時候可以直接越過記憶體和磁碟,請求網路
因為User的動作的目的性明確,普通情況可以使用快取,你也可以視情況自己定製

定製快取策略.png
public enum NetworkPolicy { NO_CACHE(1 << 0),//跳過檢查磁碟快取,強制通過網路載入 NO_STORE(1 << 1),//不將結果儲存到磁碟快取 OFFLINE(1 << 2);//強制使用磁碟快取,跳過網路 public enum MemoryPolicy { NO_CACHE(1 << 0),//處理請求時跳過記憶體快取查詢 NO_STORE(1 << 1);//不將最終結果儲存到記憶體快取中。 用於一次性請求,以避免從快取中刪除其他圖片快取。
單擊三級快取,長按請求網路
String url = "http://192.168.43.60:8080/imgs/HXqqASHJETSlvpnc.jpg"; imageView.setOnClickListener(v -> { Picasso.get() .load(url) .into(imageView); }); imageView.setOnLongClickListener(v -> { Picasso.get() .load(url) .networkPolicy(NetworkPolicy.NO_CACHE)//跳過磁碟快取 .memoryPolicy(MemoryPolicy.NO_CACHE) //跳過記憶體快取 .into(imageView); return true; });
三、Picasso的圖片變換
ImageView:300dp*300dp 資源圖片:3600px*2400px

測試圖.png
1.對比一下點選前後的變化
這個是使用Picasso

點選前後.png
直接 BitmapFactory.decodeFile

BitmapFactory.decodeFile.png
可見基本上差不多,說明Picasso在載入大圖是,預設情況下並未優化
2. resize
方法和 resizeDimen
resize方法可以對大圖進行優化,但本地快取的大小依然是原圖大小
兩者本質上一樣resizeDimen是使用dimens的尺寸資源,可以dp

resize.png

重置尺寸.png
3.fit和centerCrop
注意centerCrop有個一參的入參:Gravity.XXX來控制裁剪的位置(預設中心裁剪)
centerCrop必須呼叫resize才行,fit呼叫後, deferred = true;
在into方法中會觸發resize
另外fit不能和resize共存
java.lang.IllegalStateException: Center crop requires calling resize with positive width and height.

fit.png
4. .transform
總得來說,就是針對Bitmap做一些操作,可參見Bitmap專題,再把新的Bitmap返回出去
下面給出三個簡單的操作,灰度,模糊,路徑裁剪

變化.png
---->[灰度操作]------------ public class GrayTransformation implements Transformation { @Override public Bitmap transform(Bitmap source) { Bitmap bmpGrayScale = Bitmap.createBitmap( source.getWidth(), source.getHeight(), Bitmap.Config.RGB_565); Canvas c = new Canvas(bmpGrayScale); Paint paint = new Paint(); ColorMatrix cm = new ColorMatrix(); cm.setSaturation(0); paint.setColorFilter(new ColorMatrixColorFilter(cm)); c.drawBitmap(source, 0, 0, paint); if (source != bmpGrayScale) { source.recycle(); } return bmpGrayScale; } @Override public String key() { return "BlurTransformation"; } } ---->[模糊操作]------------ public class BlurTransformation implements Transformation { private Context mContext; private int mRadius; public BlurTransformation(Context context, int radius) { mContext = context; mRadius = radius; } @Override public Bitmap transform(Bitmap source) { RenderScript rs = RenderScript.create(mContext); Bitmap blurredBitmap = source.copy(Bitmap.Config.ARGB_8888, true); Allocation input = Allocation.createFromBitmap(rs, blurredBitmap, Allocation.MipmapControl.MIPMAP_FULL, Allocation.USAGE_SHARED); Allocation output = Allocation.createTyped(rs, input.getType()); ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); script.setInput(input); script.setRadius(mRadius); script.forEach(output); output.copyTo(blurredBitmap); source.recycle(); return blurredBitmap; } @Override public String key() { return "BlurTransformation"; } } ---->[星星裁剪類]------------ /** * 作者:張風捷特烈<br/> * 時間:2018/8/30 0030:21:44<br/> * 郵箱:[email protected]<br/> * 說明:星星裁剪類 */ public class StarTransformation implements Transformation { private int num; private boolean mOutline; public StarTransformation(int num,boolean outline) { this.num = num; mOutline = outline; } @Override public Bitmap transform(Bitmap source) { int size = Math.min(source.getWidth(), source.getHeight()); int x = (source.getWidth() - size) / 2; int y = (source.getHeight() - size) / 2; Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size); if (squaredBitmap != source) { source.recycle(); } int strokeWidth = (int) (size / 120f); Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig()); Canvas canvas = new Canvas(bitmap); Paint avatarPaint = new Paint(); BitmapShader shader = new BitmapShader(squaredBitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAM avatarPaint.setShader(shader); Paint outlinePaint = new Paint(); outlinePaint.setColor(Color.WHITE); outlinePaint.setStyle(Paint.Style.STROKE); outlinePaint.setStrokeWidth(strokeWidth); outlinePaint.setAntiAlias(true); Path starPath = nStarPath(num, size / 2, size / 2 * 0.8f); canvas.drawPath(starPath, avatarPaint); if (mOutline) { canvas.drawPath(starPath, outlinePaint); } squaredBitmap.recycle(); return bitmap; } private Path nStarPath(int num, float R, float r) { Path path = new Path(); float perDeg = 360 / num; float degA = perDeg / 2 / 2; float degB = 360 / (num - 1) / 2 - degA / 2 + degA; float dx = R * cos(degA); float dy = R; path.moveTo(cos(degA) * R + dx, -sin(degA) * R + dy); for (int i = 0; i <= num; i++) { path.lineTo(cos(degA + perDeg * i) * R + dx, -sin(degA + perDeg * i) * R + dy); path.lineTo(cos(degB + perDeg * i) * r + dx, -sin(degB + perDeg * i) * r + dy); } path.close(); return path; } private float sin(float deg) { return (float) Math.sin(deg / 180 * Math.PI); } private float cos(float deg) { return (float) Math.cos(deg / 180 * Math.PI); } @Override public String key() { return "StarTransformation"; } }
四、常規使用
1.其他設定

旋轉.png
.placeholder(R.mipmap.icon_default)//預設佔位圖 .error(R.mipmap.error)//錯誤顯示圖 .rotate(90)//旋轉90度 .noFade()//取消漸變---預設有漸變
2.載入的形式
說是四種,核心都差不多,就是找資源而已

四種載入方式.png
String url = "http://192.168.10.104:8080/imgs/HXqqASHJETSlvpnc.jpg"; File file = new File(getCacheDir(), "/picasso-cache/200ca0eb49c069b127236c34582a5c10.1"); Uri uri = Uri.parse("file:///android_asset/wy.jpg"); Picasso.get() //.load(url)//載入url //.load(R.mipmap.icon_default)//載入資原始檔 //.load(file)//載入檔案 .load(uri)//assets檔案---Uri形式
3.自己可以完成一下下面的效果

Picasso的基本用法也就這麼多,明天進原始碼裡去看看
後記:捷文規範
1.本文成長記錄及勘誤表
專案原始碼 | 日期 | 附錄 |
---|---|---|
V0.1-- | 2018-2-11 | 無 |
釋出名: 開源框架之[-Picasso-]應用篇
捷文連結: https://www.jianshu.com/p/075f846207a9
2.更多關於我
筆名 | 微信 | |
---|---|---|
張風捷特烈 | 1981462002 | zdl1994328 |
我的github: https://github.com/toly1994328
我的簡書: https://www.jianshu.com/u/e4e52c116681
我的掘金: https://juejin.im/user/5b42c0656fb9a04fe727eb37
個人網站: http://www.toly1994.com
3.宣告
1----本文由張風捷特烈原創,轉載請註明
2----歡迎廣大程式設計愛好者共同交流
3----個人能力有限,如有不正之處歡迎大家批評指證,必定虛心改正
4----看到這裡,我在此感謝你的喜歡與支援

icon_wx_200.png