目前經常使用的開源圖片加載框架有:1.Universal-Image-Loader,該項目存在於Github上面https://github.com/nostra13/Android-Universal-Image-Loader;java
2.fresco,該項目的中文網站是:http://www.fresco-cn.org/,在Github上面是:https://github.com/facebook/frescoandroid
以前一直用的是Universal-Image-Loader,改用fresco以後,在有大圖展現的頁面,能明顯感受到fresco在渲染速度和圖片呈現效果上更勝一籌。fresco與Universal-Image-Loader比起來,最直觀的幾個優勢是:
1.在顯示圓形、圓角圖片時,不須要另行引入CircleImageView等第三方或者自定義控件;
2.更容易實現圖片View的點擊效果;
3.默認的漸入顯示效果;git
下面來講一下fresco的使用:github
1.若是使用的是Android Studio,則須要在build.gradle中引入fresco項目:web
- dependencies {
- ......
- compile 'com.facebook.fresco:fresco:0.9.0+'
- ......
其中0.9.0是fresco的版本;緩存
2.在程序顯示圖片以前調用init接口,通常會在Application的onCreate方法中調用Fresco.initialize()方法,該方法有兩種傳參方式:網絡
- public static void initialize(Context context)
-
- public static void initialize(Context context, ImagePipelineConfig imagePipelineConfig)
其中不對ImagePipeline進行配置的話,Fresco將採用默認的配置。ImagePipelineConfig能夠進行以下配置:app
- public ImagePipelineConfig getImagePipelineConfig() {
- ImagePipelineConfig config = ImagePipelineConfig.newBuilder(App.getAppContext())
- .setWebpSupportEnabled(true)
-
- .setDownsampleEnabled(true)
-
- .setResizeAndRotateEnabledForNetwork(true)
-
- .setDecodeMemoryFileEnabled(true)
-
- .setBitmapsConfig(Bitmap.Config config)
-
- .setBitmapMemoryCacheParamsSupplier(bitmapCacheParamsSupplier)
-
- .setEncodedMemoryCacheParamsSupplier(encodedCacheParamsSupplier)
-
- .setMainDiskCacheConfig(mainDiskCacheConfig)
-
- .setExecutorSupplier(executorSupplier)
-
- .setImageCacheStatsTracker(imageCacheStatsTracker)
-
- .setMemoryTrimmableRegistry(memoryTrimmableRegistry)
-
- .setNetworkFetchProducer(networkFetchProducer)
-
- .setProgressiveJpegConfig(progressiveJpegConfig)
-
- .setSmallImageDiskCacheConfig(smallImageDiskCacheConfig)
- .build();
- return config;
- }
這裏要介紹一下fresco的三級緩存:Bitmap緩存+編碼/未解碼圖片緩存+硬盤緩存。Fresco的加載圖片的流程爲:查找Bitmap緩存中是否存在,存在則直接返回Bitmap直接使用,不存在則查找未解碼圖片的緩存,若是存在則進行Decode成Bitmap而後直接使用並加入Bitmap緩存中,若是未解碼圖片緩存中查找不到,則進行硬盤緩存的檢查,若有,則進行IO、轉化、解碼等一系列操做,最後成Bitmap供咱們直接使用,並把未解碼(Encode)的圖片加入未解碼圖片緩存,把Bitmap加入Bitmap緩存中,如硬盤緩存中沒有,則進行Network操做下載圖片,而後加入到各個緩存中。ImagePipelineConfig及fresco的緩存原理詳見:http://blog.csdn.net/u010687392/article/details/50266633框架
3.使用com.facebook.drawee.view.SimpleDraweeView替換掉ImageView。SimpleDraweeView能夠經過配置實現圓形、圓角、pressed效果、默認圖片、加載失敗圖片等顯示效果,在佈局中能夠以下配置(以圓形效果爲例):ide
- <com.facebook.drawee.view.SimpleDraweeView
- android:id="@+id/iv_user_avatar"
- android:layout_width="@dimen/common_big_user_portrait_height"
- android:layout_height="@dimen/common_big_user_portrait_height"
- android:layout_centerInParent="true"
-
- fresco:actualImageScaleType="centerCrop"
-
- fresco:failureImage="@drawable/default_user_portrait"
- fresco:failureImageScaleType="centerCrop"
-
- fresco:placeholderImage="@drawable/default_user_portrait"
- fresco:placeholderImageScaleType="centerCrop"
-
- fresco:pressedStateOverlayImage="@drawable/common_circle_image_pressed"
-
- fresco:roundAsCircle="true"
- />
若是是圓角的話,能夠在上面的基礎上增長以下特殊配置,其中fresco:roundedCornerRadius根據須要具體設置值:
- fresco:roundAsCircle="false"
- fresco:roundBottomLeft="true"
- fresco:roundBottomRight="true"
- fresco:roundTopLeft="true"
- fresco:roundTopRight="true"
- fresco:roundedCornerRadius="xdp"
而後在代碼中,調用以下語句便可顯示網絡或者本地圖片:
- String uri = bean.getUrl();
- if (!uri.startsWith("http")) {
- uri = "file://" + bean.getUrl();
- }
若是就是想讓view顯示默認的圖片,則調用語句:
- simpleDraweeView.setImageURI(Uri.parse(「」));
若是想修改默認的ImageRequest、DraweeController等的配置,則能夠在代碼中這樣配置和顯示圖片(以顯示圓形圖片爲例):
- public void displayCirclePortraitImage(Context context, String picUrl, SimpleDraweeView iv_pic) {
- if (iv_pic == null) {
- return;
- }
- Context tempContext = context;
- if (tempContext == null) {
- tempContext = App.getAppContext();
- }
- if (!StringUtil.isEmpty(picUrl)) {
- Uri uri = Uri.parse(picUrl);
- ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
- .setLocalThumbnailPreviewsEnabled(true)
- .setAutoRotateEnabled(true)
- .setLowestPermittedRequestLevel(ImageRequest.RequestLevel.FULL_FETCH)
- .setProgressiveRenderingEnabled(false)
- .build();
- DraweeController controller = Fresco.newDraweeControllerBuilder()
- .setImageRequest(request)
- .setAutoPlayAnimations(true)
- .setOldController(iv_pic.getController())
- .build();
- iv_pic.setController(controller);
- } else {
- iv_pic.setImageURI(Uri.parse(""));
- }
- GenericDraweeHierarchyBuilder gbulder = new GenericDraweeHierarchyBuilder(tempContext.getResources());
- ghy = gbulder.setActualImageScaleType(ScalingUtils.ScaleType.CENTER_CROP)
- .setPlaceholderImage(tempContext.getResources().getDrawable(R.drawable.default_user_portrait), ScalingUtils.ScaleType.CENTER_CROP)
- .setFailureImage(tempContext.getResources().getDrawable(R.drawable.default_user_portrait), ScalingUtils.ScaleType.CENTER_CROP)
- .setRoundingParams(RoundingParams.asCircle())
- .setPressedStateOverlay(tempContext.getResources().getDrawable(R.drawable.common_circle_image_pressed))
- .build();
- iv_pic.setHierarchy(ghy);
- float scaleRadio = 1.0f;
- iv_pic.setAspectRatio(scaleRadio);
- }
若是隻想下載圖片,不使用SimpleDraweeView控件,則能夠經過以下方法:
- public void loadImage(Context context, String picUrl, ResizeOptions resizeOptions, BaseBitmapDataSubscriber bitmapDataSubscriber) {
- if (StringUtil.isEmpty(picUrl)) {
- return;
- }
- Uri uri = Uri.parse(picUrl);
- ImageRequest imageRequest = ImageRequestBuilder.newBuilderWithSource(uri)
- .setLocalThumbnailPreviewsEnabled(true)
- .setAutoRotateEnabled(true)
- .setResizeOptions(resizeOptions)
- .setLowestPermittedRequestLevel(ImageRequest.RequestLevel.FULL_FETCH)
- .setProgressiveRenderingEnabled(false)
- .build();
-
- ImagePipeline imagePipeline = Fresco.getImagePipeline();
- DataSource<CloseableReference<CloseableImage>>
- dataSource = imagePipeline.fetchDecodedImage(imageRequest, context);
- dataSource.subscribe(bitmapDataSubscriber, CallerThreadExecutor.getInstance());
- }
其中回調接口BaseBitmapDataSubscriber實現以下:
- FrescoImageLoader.getInstance().loadImage(ViewSinglePhotoActivity.this, picUrl, resizeOptions, new
- BaseBitmapDataSubscriber() {
- @Override
- protected void onNewResultImpl(Bitmap bitmap) {
- ViewSinglePhotoActivity.this.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- loadPb.setVisibility(View.GONE);
- }
- });
- if (bitmap != null && photoView != null) {
- final Bitmap arg2 = Bitmap.createBitmap(bitmap);
- ImageCache.getInstance().put(picUrl, arg2);
- ViewSinglePhotoActivity.this.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- photoView.setImageBitmap(arg2);
- }
- });
- }
- }
-
- @Override
- protected void onFailureImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
- ViewSinglePhotoActivity.this.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- loadPb.setVisibility(View.GONE);
- photoView.setImageResource(R.drawable.default_pic);
- }
- });
- }
- });
注意事項:
1.佈局中若是使用了fresco的屬性,則須要引入命名空間:
xmlns:fresco="http://schemas.android.com/apk/res-auto"
2.SimpleDraweeView不支持wrap_content屬性,必須給出具體的寬高值,若是width或者height其中有一個值爲wrap_content,則能夠經過設置寬高比的方法setAspectRatio間接指定其值;
3.使用SimpleDraweeView後,facebook官方建議不要再使用ImageView的任何屬性,如setImageResource、setBackground、setScaleType等;後續版本SimpleDraweeView旨在改成直接繼承View;
4.GenericDraweeHierarchy的屬性配置要麼在佈局中設置完,要麼在代碼中設置完;simpleDraweeView.getHierarchy()的值一直都不爲空,因此不要用這個判斷條件來作區分;
5.關於OOM,1.請給ImageRequest默認配置上setResizeOptions(resizeOptions)屬性;對於照片牆等含有大量圖片的頁面,必需要對圖片的大小作限制;網絡圖片能夠經過服務端來對圖片的尺寸、質量、圖片類型作處理後再返給客戶端,可是對於手機本地的圖片,就只能經過setResizeOptions來有效下降內存緩存的開銷;2.在低內存的狀況下或者退出多圖頁面的狀況下,手動釋放內存緩存:
- ImagePipeline imagePipeline = Fresco.getImagePipeline();
- imagePipeline.clearMemoryCaches();
- imagePipeline.clearDiskCaches();
- imagePipeline.clearCaches();
6.BaseBitmapDataSubscriber的方法onNewResultImpl中返回的Bitmap會很快被系統回收掉,因此須要再複製一份自行保存;保存時能夠採用LruCache方法。
7.對於webp格式的網絡圖片內容,若是引入的是fresco:0.6.0;則在安卓4.2.2的手機上沒有問題,若是引入的是fresco:0.8.0或者fresco:0.9.0,則在安卓4.2.2的手機上圖片會加載失敗。