這兩天修改公司外部項目時,發現對方在項目中使用了fresco,正好趁這個機會,對fresco進行一次詳細的梳理。
fresco相當于一個獨立的圖片管家,使用它之后你就不用再去關心圖片的加載和顯示問題,這些繁瑣的事情fresco都會自動幫你解決還有就是在動圖加載中,加載Gif圖和WebP動圖在任何一個Android開發者眼里看來都是一件非常頭疼的事情。每一幀都是一張很大的Bitmap,每一個動畫都有很多幀。Fresco讓你沒有這些煩惱,它處理好每一幀并管理好你的內存。
fresco官網:http://www.fresco-cn.org/
fresco先包括兩個大板塊:Image Pipeline和Drawees.
Image Pipeline
Fresco 中設計有一個叫做 Image Pipeline 的模塊。它負責從網絡,從本地文件系統,本地資源加載圖片。為了最大限度節省空間和CPU時間,它含有3級緩存設計(2級內存,1級磁盤)。
特性:
1.內存管理方面:
解壓后的圖片,即Android中的Bitmap,占用大量的內存。大的內存占用勢必引發更加頻繁的GC。在5.0以下,GC將會顯著地引發界面卡頓。
在5.0以下系統,Fresco將圖片放到一個特別的內存區域。當然,在圖片不顯示的時候,占用的內存會自動被釋放。這會使得APP更加流暢,減少因圖片內存占用而引發的OOM。
Fresco 在低端機器上表現一樣出色,你再也不用因圖片內存占用而思前想后。
2.圖片繪制方面
Fresco 的 Drawees 設計,帶來一些有用的特性:
自定義居中焦點
圓角圖,當然圓圈也行
下載失敗之后,點擊重現下載
自定義占位圖,自定義overlay, 或者進度條
指定用戶按壓時的overlay
Drawees
Fresco 中設計有一個叫做 Drawees 模塊,它會在圖片加載完成前顯示占位圖,加載成功后自動替換為目標圖片。當圖片不再顯示在屏幕上時,它會及時地釋放內存和空間占用
特性:
1.圖片加載方面:
Fresco的Image Pipeline允許你用很多種方式來自定義圖片加載過程,比如:
為同一個圖片指定不同的遠程路徑,或者使用已經存在本地緩存中的圖片
先顯示一個低清晰度的圖片,等高清圖下載完之后再顯示高清圖
加載完成回調通知
對于本地圖,如有EXIF縮略圖,在大圖加載完成之前,可先顯示縮略圖
縮放或者旋轉圖片
對已下載的圖片再次處理
支持WebP解碼,即使在早先對WebP支持不完善的Android系統上也能正常使用!
2.圖片的漸進式呈現
漸進式的JPEG圖片格式已經流行數年了,漸進式圖片格式先呈現大致的圖片輪廓,然后隨著圖片下載的繼續,呈現逐漸清晰的圖片,這對于移動設備,尤其是慢網絡有極大的利好,可帶來更好的用戶體驗。
Android 本身的圖片庫不支持此格式,但是Fresco支持。使用時,和往常一樣,僅僅需要提供一個圖片的URI即可,剩下的事情,Fresco會處理。
具體一些詳細的操作,查看API(http://fresco-cn.org/docs/supported-uris.html)
就可以理解了,下面就一些可能會出現的問題進行說明:
1.在使用AndroidStudio進行開發時,剛開始在項目()build.gradle添加下面代碼:
dependencies
{
compile
'com.facebook.fresco:fresco:0.5.0+'
}
但很多情況下項目會提示缺少包,這是因為官方文檔已經說fresco的類庫發布到了Maven中央庫,而我們可能沒有在總Project下的build.gradle文件中添加下面代碼:
allprojects {
repositories {
jcenter()
mavenCentral()
}
}
2.現在來說說最簡單的使用:就是加載網絡圖片,
第一:在你的application類onCreate方法中添加
Fresco.initialize(instance);
第二:fresco是通過控件來實現它內部的優化緩存處理,我們使用的時候是通過控件來使用,具體如下
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/user_avator"
android:layout_width="50dp"
android:layout_height="50dp"
fresco:roundAsCircle="true"
fresco:roundedCornerRadius="180dp"
fresco:actualImageScaleType="focusCrop"
android:layout_centerVertical="true" />
大家可能看到,屬性中存在fresco:開頭的聲明。這個是fresco的自定義屬性,如果我們需要使用其自定義屬性,必須在我們的xml根布局中添加聲明/命名空間,這點需要注意
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
第三:在代碼中具體的使用
Uri uri = Uri.parse(http://b.hiphotos.baidu.com/image/pic/item/e78.jpg);
mAvatorImg.setImageURI(uri);
3.現在介紹一些fresco的屬性,通過這些屬性我們可以很方便的定制一些效果
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/my_image_view"
android:layout_width="20dp" // 不支持wrap_content 如果要設置寬高比, 需要在Java代碼中指定setAspectRatio(1.33f);
android:layout_height="20dp"http:// 不支持wrap_content
fresco:fadeDuration="300"
fresco:actualImageScaleType="focusCrop"
// 設置圖片縮放. 通常使用focusCrop,該屬性值會通過算法把人頭像放在中間
fresco:placeholderImage="@color/wait_color"
// 下載成功之前顯示的圖片
fresco:placeholderImageScaleType="fitCenter"
fresco:failureImage="@drawable/error"
// 加載失敗的時候顯示的圖片
fresco:failureImageScaleType="centerInside"
fresco:retryImage="@drawable/retrying"
// 加載失敗,提示用戶點擊重新加載的圖片(會覆蓋failureImage的圖片)
fresco:retryImageScaleType="centerCrop"
fresco:progressBarImage="@drawable/progress_bar"http:// 提示用戶正在加載,和加載進度無關
fresco:progressBarImageScaleType="centerInside"
fresco:progressBarAutoRotateInterval="1000"
fresco:backgroundImage="@color/blue"
fresco:overlayImage="@drawable/watermark"
fresco:pressedStateOverlayImage="@color/red"
fresco:roundAsCircle="false"
// 是不是設置圓圈
fresco:roundedCornerRadius="1dp"
// 圓角角度,180的時候會變成圓形圖片
fresco:roundTopLeft="true"
fresco:roundTopRight="false"
fresco:roundBottomLeft="false"
fresco:roundBottomRight="true"
fresco:roundWithOverlayColor="@color/corner_color"
fresco:roundingBorderWidth="2dp"
fresco:roundingBorderColor="@color/border_color"
/>
修改圖片尺寸
Uri uri = "file:///mnt/sdcard/MyApp/myfile.jpg";
int width = 50, height = 50;
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
.setResizeOptions(new ResizeOptions(width, height))
.build();
PipelineDraweeController controller = Fresco.newDraweeControllerBuilder()
.setOldController(mDraweeView.getController())
.setImageRequest(request)
.build();
mSimpleDraweeView.setController(controller);
自動旋轉
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
.setAutoRotateEnabled(true)
.build();