Fresco架構的簡單使用

一、

        1.Fresco介紹

                 Fresco是Facebook最新推出的一款用於Android應用中展示圖片的強大圖片庫,可以從網絡、本地存儲和本地資源中加載圖片。相對於ImageLoader,擁有更快的圖片下載速度以及可以加載和顯示gif圖等諸多優勢,是個很好的圖片框架。

        2.Fresco特點

                1)內存管理

                        a)在5.0以下系統,Fresco將圖片放到一個特別的內存區域。當然,在圖片不顯示的時候,佔用的內存會自動被釋放。這會使得APP更加流暢,減少因圖片內存佔用而引發的OOM。  

                        b)內存分配採用:系統匿名共享內存

                2)漸進式呈現圖片

                        漸進式圖片格式先呈現大致的圖片輪廓,然後隨着圖片下載的繼續, 呈現逐漸清晰的圖片,這對於移動設備,尤其是慢網絡有極大的利好,可帶來更好的用戶體驗。

                3)支持加載Gif圖,支持WebP格式。

                4)圖像的呈現

                        a)自定義居中焦點(對人臉等圖片顯示非常有幫助)。

                        b)圓角圖,當然圓圈也行。

                        c)下載失敗之後,點擊重新下載。

                        d)自定義佔位圖,自定義overlay, 或者進度條。

                        e)指定用戶按壓時的overlay。


                5)圖像的加載

                            a)爲同一個圖片指定不同的遠程路徑,或者使用已經存在本地緩存中的圖片。

                            b)先顯示一個低解析度的圖片,等高清圖下載完之後再顯示高清圖。

                            c)加載完成回調通知。

                            d)對於本地圖,如有EXIF縮略圖,在大圖加載完成之前,可先顯示縮略圖。

                             e)縮放或者旋轉圖片。

                             f)處理已下載的圖片。

                6)項目地址

                       項目地址: https://github.com/facebook/fresco

                        官方網站:http://fresco-cn.org/docs/index.html

                

二、Fresco的使用

        1.Fresco支持的URI

                1)網絡圖片     http://, https://                

                2)本地文件     file://

                3)Content provider     content://

                4)asset目錄下的資源    asset://

                5)res目錄下的資源   res://

                6)Uri中指定圖片數據   data:mime/type;base64,

        2.Fresco常用API   

android:layout_width="20dp"	  // 不支持wrap_content, 如果要設置寬高比, 需要在Java代碼中指定setAspectRatio(float ratio);
android:layout_height="20dp"    // 不支持wrap_content 
fresco:placeholderImage="@color/wait_color"     // 下載成功之前顯示的圖片
fresco:placeholderImageScaleType="fitCenter"    // 設置圖片縮放. 通常使用focusCrop,該屬性值會通過算法把人頭像放在中間
fresco:failureImage="@drawable/error"     // 加載失敗的時候顯示的圖片
fresco:failureImageScaleType=“centerInside"     // 設置圖片縮放
fresco:retryImage="@drawable/retrying"       // 加載失敗,提示用戶點擊重新加載的圖片(會覆蓋failureImage的圖片)
fresco:roundAsCircle="true"      // 設置圓形方式顯示圖片
    // 圓角設置
    fresco:roundedCornerRadius="1dp"
    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"

        3.使用步驟

            1)添加依賴

dependencies {
  // 在 API < 14 上的機器支持 WebP 時,需要添加
  compile 'com.facebook.fresco:animated-base-support:0.14.1'

  // 支持 GIF 動圖,需要添加
  compile 'com.facebook.fresco:animated-gif:0.14.1'

  // 支持 WebP (靜態圖+動圖),需要添加
  compile 'com.facebook.fresco:animated-webp:0.14.1'
  compile 'com.facebook.fresco:webpsupport:0.14.1'

  // 僅支持 WebP 靜態圖,需要添加
  compile 'com.facebook.fresco:webpsupport:0.14.1'

	compile 'com.facebook.fresco:fresco:0.14.1'
}

            2)在application中初始化Fresco

            Fresco.initialize(this);

            3)配置網絡權限

            <uses-permission android:name="android.permission.INTERNET"/>

            4)在xml佈局文件中,加入命名空間

<!-- 其他元素-->
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    android:layout_height="match_parent"
    android:layout_width="match_parent">

                5)在xml中引入SimpleDraweeView

<com.facebook.drawee.view.SimpleDraweeView
    android:id="@+id/my_image_view"
    android:layout_width="130dp"
    android:layout_height="130dp"
    fresco:placeholderImage="@drawable/my_drawable"
  />

                6)在Java代碼中開始加載圖片

Uri uri = Uri.parse("https://raw.githubusercontent.com/facebook/fresco/gh-pages/static/logo.png");
SimpleDraweeView draweeView = (SimpleDraweeView) findViewById(R.id.my_image_view);
draweeView.setImageURI(uri);

        4.注意事項

                如果項目中使用了OkHttp需要進行替換。

                For OkHttp2:

            compile "com.facebook.fresco:imagepipeline-okhttp:0.12.0+"

                For OkHttp3:

            compile "com.facebook.fresco:imagepipeline-okhttp3:0.12.0+"

三、Fresco使用實例

        1.項目準備

                1)佈局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_fresco"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include layout="@layout/titlebar"></include>

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <Button
                android:id="@+id/bt_fresco_spimg"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="5dp"
                android:text="帶進度條的圖片" />

            <Button
                android:id="@+id/bt_fresco_crop"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="5dp"
                android:text="圖片的不同裁剪" />

            <Button
                android:id="@+id/bt_fresco_circleAndCorner"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="5dp"
                android:text="圓形和圓角圖片" />

            <Button
                android:id="@+id/bt_fresco_jpeg"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="5dp"
                android:text="漸進式展示圖片" />

            <Button
                android:id="@+id/bt_fresco_gif"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="5dp"
                android:text="GIF動畫圖片" />

            <Button
                android:id="@+id/bt_fresco_multi"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="5dp"
                android:text="多圖請求及圖片複用" />

            <Button
                android:id="@+id/bt_fresco_listener"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="5dp"
                android:text="圖片加載監聽" />

            <Button
                android:id="@+id/bt_fresco_resize"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="5dp"
                android:text="圖片修改和旋轉" />

            <Button
                android:id="@+id/bt_fresco_modifyImg"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="5dp"
                android:text="修改圖片" />

            <Button
                android:id="@+id/bt_fresco_autoSizeImg"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="5dp"
                android:text="動態展示圖片" />
        </LinearLayout>
    </ScrollView>
</LinearLayout>

                2)代碼

        // 設置帶進度條樣式
        GenericDraweeHierarchyBuilder builder = new GenericDraweeHierarchyBuilder(getResources());
        GenericDraweeHierarchy hierarchy = builder.setProgressBarImage(new ProgressBarDrawable()).build();
        sdvFresco.setHierarchy(hierarchy);
        // 加載圖片地址
        Uri uri = Uri.parse("http://img4.duitang.com/uploads/item/201211/24/20121124175330_ruKEK.jpeg");
        // 設置顯示圖片
        sdvFresco.setImageURI(uri);

        2.帶進度條的圖片

                1)佈局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_fresco_spimg3"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include layout="@layout/titlebar"></include>

    <com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/sdv_fresco"
        android:layout_width="150dp"
        android:layout_height="150dp" />

</LinearLayout>

                2)代碼

        // 設置帶進度條樣式
        GenericDraweeHierarchyBuilder builder = new GenericDraweeHierarchyBuilder(getResources());
        GenericDraweeHierarchy hierarchy = builder.setProgressBarImage(new ProgressBarDrawable()).build();
        sdvFresco.setHierarchy(hierarchy);
        // 加載圖片地址
        Uri uri = Uri.parse("http://img4.duitang.com/uploads/item/201211/24/20121124175330_ruKEK.jpeg");
        // 設置顯示圖片
        sdvFresco.setImageURI(uri);

        3.圖片的不同裁剪

                1)佈局

<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:gravity="center_horizontal"
    android:orientation="vertical">

    <include layout="@layout/titlebar"></include>

    <com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/sdv_fresco_crop"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_marginTop="48dp"
        android:background="@android:color/black"
        fresco:placeholderImage="@drawable/atguigu_logo" />

    <TextView
        android:id="@+id/tv_fresco_explain"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:gravity="center"
        android:textSize="16sp" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="48dp"
        android:orientation="vertical">

        <Button
            android:id="@+id/bt_fresco_center"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="center" />

        <Button
            android:id="@+id/bt_fresco_centercrop"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="centerCrop" />

        <Button
            android:id="@+id/bt_fresco_focuscrop"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="focuscrop" />

        <Button
            android:id="@+id/bt_fresco_centerinside"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="centerInside" />

        <Button
            android:id="@+id/bt_fresco_fitcenter"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="fitCenter" />

        <Button
            android:id="@+id/bt_fresco_fitstart"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="fitstart" />

        <Button
            android:id="@+id/bt_fresco_fitend"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="fitEnd" />

        <Button
            android:id="@+id/bt_fresco_fitxy"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="fitxy" />

        <Button
            android:id="@+id/bt_fresco_none"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="none" />

    </LinearLayout>
    </ScrollView>

</LinearLayout>

                2)代碼設置

 // 居中,無縮放
    @OnClick(R.id.bt_fresco_center)
    void bt_fresco_center_click(View view){

    }

    // 保持寬高比縮小或放大,使得兩邊都大於或等於顯示邊界。居中顯示
    @OnClick(R.id.bt_fresco_centercrop)
    void bt_fresco_centercrop_click(View view){

    }

    // 同centerCrop, 但居中點不是中點,而是指定的某個點,這裏我設置爲圖片的左上角那點
    @OnClick(R.id.bt_fresco_focuscrop)
    void bt_fresco_focuscrop_click(View view){

    }

    // 使兩邊都在顯示邊界內,居中顯示。如果圖尺寸大於顯示邊界,則保持長寬比縮小圖片
    @OnClick(R.id.bt_fresco_centerinside)
    void bt_fresco_centerinside_click(View view){

    }

    // 保持寬高比,縮小或者放大,使得圖片完全顯示在顯示邊界內。居中顯示
    @OnClick(R.id.bt_fresco_fitcenter)
    void bt_fresco_fitcenter_click(View view){

    }

    // 保持寬高比,縮小或者放大,使得圖片完全顯示在顯示邊界內,不居中,和顯示邊界左上對齊
    @OnClick(R.id.bt_fresco_fitstart)
    void bt_fresco_fitstart_click(View view){

    }

    // 保持寬高比,縮小或者放大,使得圖片完全顯示在顯示邊界內,不居中,和顯示邊界右下對齊
    @OnClick(R.id.bt_fresco_fitend)
    void bt_fresco_fitend_click(View view){

    }

    // 不保持寬高比,填充滿顯示邊界
    @OnClick(R.id.bt_fresco_fitxy)
    void bt_fresco_fitxy_click(View view){

    }

    // 如要使用title mode顯示, 需要設置爲none
    @OnClick(R.id.bt_fresco_none)
    void bt_fresco_none_click(View view){

    }

                3)代碼展示圖片

    private void imageDisplay() {
        sdvFrescoCrop.setHierarchy(hierarchy);
        Uri uri = Uri.parse("http://img4q.duitang.com/uploads/item/201305/20/20130520115416_VrUUR.jpeg");
        sdvFrescoCrop.setImageURI(uri);
    }

        4.圓形和圓角圖

                1)佈局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include layout="@layout/titlebar"></include>

    <com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/sdv_fresco_circleandcorner"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_gravity="center"
        fresco:placeholderImage="@drawable/atguigu_logo" />

    <Button
        android:id="@+id/bt_fresco_circle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="48dp"
        android:text="設置圓形圖片" />

    <Button
        android:id="@+id/bt_fresco_corner"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="設置圓角圖片" />

</LinearLayout>

                2)設置圓形圖片

uri = Uri.parse("http://img4q.duitang.com/uploads/item/201304/27/20130427043538_wAfHC.jpeg");
        builder = new GenericDraweeHierarchyBuilder(getResources());

     // 設置圓形圖片
    @OnClick(R.id.bt_fresco_circle)
    void bt_fresco_circle_click(View view) {

        // 參數設置爲圓形
        params = RoundingParams.asCircle();
        GenericDraweeHierarchy hierarchy = builder.setRoundingParams(params).build();
        sdvFrescoCircleandcorner.setHierarchy(hierarchy);

        // 加載圖片
        sdvFrescoCircleandcorner.setImageURI(uri);
    }

                3)設置圓角圖片

uri = Uri.parse("http://img4q.duitang.com/uploads/item/201304/27/20130427043538_wAfHC.jpeg");
        builder = new GenericDraweeHierarchyBuilder(getResources());

    // 設置圓角圖片
    @OnClick(R.id.bt_fresco_corner)
    void bt_fresco_corner_click(View view) {
        // 配置參數
        params = RoundingParams.fromCornersRadius(50f);//設置圓角大小
        params.setOverlayColor(getResources().getColor(android.R.color.holo_red_light));//覆蓋層
        params.setBorder(getResources().getColor(android.R.color.holo_blue_light), 5);//邊框
        params.setRoundAsCircle(true);//如果是RoundingParams.fromCornersRadius,這個可以強制進行圓形展示

        // 設置圓形參數
        GenericDraweeHierarchy hierarchy = builder.setRoundingParams(params).build();
        sdvFrescoCircleandcorner.setHierarchy(hierarchy);

        // 加載圖片
        sdvFrescoCircleandcorner.setImageURI(uri);
    }

        5.漸進式展示圖片

            1)佈局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_fresco_jpeg"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include layout="@layout/titlebar"></include>

    <com.facebook.drawee.view.SimpleDraweeView
        android:layout_gravity="center"
        android:id="@+id/sdv_fresco_jpeg"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_marginTop="48dp"
        fresco:placeholderImage="@drawable/atguigu_logo" />

    <Button
        android:id="@+id/sdv_fresco_askImg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="48dp"
        android:text="請求網絡圖片" />
</LinearLayout>

            2)代碼

 @OnClick(R.id.sdv_fresco_askImg)
    void sdv_fresco_askImg_click(View view){

        // 加載質量配置
        ProgressiveJpegConfig jpegConfig = new ProgressiveJpegConfig() {
            @Override
            public int getNextScanNumberToDecode(int scanNumber) {
                return scanNumber + 2;
            }

            @Override
            public QualityInfo getQualityInfo(int scanNumber) {
                boolean isGoodEnough = (scanNumber >= 5);

                return ImmutableQualityInfo.of(scanNumber, isGoodEnough, false);
            }
        };

        ImagePipelineConfig.newBuilder(this).setProgressiveJpegConfig(jpegConfig).build();
        // 獲取圖片URL
        Uri uri = Uri.parse("http://cdn.duitang.com/uploads/item/201303/12/20130312021353_45Qix.jpeg");

        // 獲取圖片請求
        ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri).setProgressiveRenderingEnabled(true).build();

        DraweeController draweeController = Fresco.newDraweeControllerBuilder()
                .setImageRequest(request)
                .setTapToRetryEnabled(true)
                .setOldController(sdvFrescoJpeg.getController())//使用oldController可以節省不必要的內存分配
                .build();

        // 設置加載的控制
        sdvFrescoJpeg.setController(draweeController);
    }

        6.Gif動畫圖片

            1)佈局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_fresco_gif"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include layout="@layout/titlebar"></include>

    <com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/sdv_fresco_gif"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_marginTop="48dp"
        android:layout_gravity="center"
        fresco:placeholderImage="@drawable/atguigu_logo" />

    <Button
        android:id="@+id/bt_fresco_askImg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="48dp"
        android:text="請求gif圖片" />

    <Button
        android:id="@+id/bt_fresco_stopAnim"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="動畫停止" />

    <Button
        android:id="@+id/bt_fresco_startAnim"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="動畫開始" />
</LinearLayout>

            2)添加依賴

compile 'com.facebook.fresco:animated-gif:0.14.1'

            3)代碼

                        a)請求圖片

    @OnClick(R.id.bt_fresco_askImg)
    void bt_fresco_askImg_click(View view) {

        // 圖片地址
        Uri uri = Uri.parse("http://www.sznews.com/humor/attachement/gif/site3/20140902/4487fcd7fc66156f51db5d.gif");

        DraweeController controller = Fresco.newDraweeControllerBuilder()
                .setUri(uri)
                .setAutoPlayAnimations(false)
                .setOldController(sdvFrescoGif.getController())
                .build();

        // 設置控制器
        sdvFrescoGif.setController(controller);
    }

                       b)開始動畫

@OnClick(R.id.bt_fresco_startAnim)
    void bt_fresco_startAnim_click(View view) {

        Animatable animation = sdvFrescoGif.getController().getAnimatable();

        if (animation != null && !animation.isRunning()) {
            animation.start();
        }
    }

                      c)停止動畫

@OnClick(R.id.bt_fresco_stopAnim)
    void bt_fresco_stopAnim_click(View view) {

        Animatable animation = sdvFrescoGif.getController().getAnimatable();

        if (animation != null && animation.isRunning()) {
            animation.stop();
        }
    }


        7.多圖請求及圖片複用

                1)佈局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_fresco_multi"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include layout="@layout/titlebar"></include>

    <com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/sdv_fresco_multi"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_gravity="center"
        android:layout_marginTop="48dp"
        fresco:placeholderImage="@drawable/atguigu_logo" />

    <Button
        android:id="@+id/bt_fresco_multiImg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="48dp"
        android:text="先顯示低分辨率的圖,然後是高分辨率的圖" />

    <Button
        android:id="@+id/bt_fresco_thumbnailImg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="本地縮略圖預覽" />

    <Button
        android:id="@+id/bt_fresco_multiplexImg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="本地圖片複用" />
</LinearLayout>

                2)代碼

                    a)先顯示低分辨率的圖,然後是高分辨率的圖

     @OnClick(R.id.bt_fresco_multiImg)
    void bt_fresco_multiImg_click(View view){
        //同一張圖片,不同品質的兩個uri
        Uri lowResUri = Uri.parse("http://img1.gamedog.cn/2012/03/11/19-120311133617-50.jpg");
        Uri highResUri = Uri.parse("http://img5.duitang.com/uploads/item/201312/03/20131203153823_Y4y8F.jpeg");

        DraweeController controller = Fresco.newDraweeControllerBuilder()
                .setLowResImageRequest(ImageRequest.fromUri(lowResUri))
                .setImageRequest(ImageRequest.fromUri(highResUri))
                .setOldController(sdvFrescoMulti.getController())
                .build();

        sdvFrescoMulti.setController(controller);
    }

                    b)本地縮略圖預覽

    @OnClick(R.id.bt_fresco_thumbnailImg)
    void bt_fresco_thumbnailImg_click(View view){

        //將本地圖片地址轉換成Uri
        Uri uri = Uri.fromFile(new File(Environment.getExternalStorageDirectory()+"/meinv1.jpg"));

        ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
                .setLocalThumbnailPreviewsEnabled(true)
                .build();

        DraweeController controller = Fresco.newDraweeControllerBuilder()
                .setImageRequest(request)
                .setOldController(sdvFrescoMulti.getController())
                .build();

        sdvFrescoMulti.setController(controller);
    }

                    c)本地圖片複用

    @OnClick(R.id.bt_fresco_multiplexImg)
    void bt_fresco_multiplexImg_click(View view){

        //本地圖片的複用
        //在請求之前,還會去內存中請求一次圖片,沒有才會先去本地,最後去網絡uri
        //本地準備複用圖片的uri  如果本地這個圖片不存在,會自動去加載下一個uri
        Uri uri1 = Uri.fromFile(new File(Environment.getExternalStorageDirectory()+"/meinv1.jpg"));
        //圖片的網絡uri
        Uri uri2 = Uri.parse("http://img5.duitang.com/uploads/item/201312/03/20131203153823_Y4y8F.jpeg");

        ImageRequest request1 = ImageRequest.fromUri(uri1);
        ImageRequest request2 = ImageRequest.fromUri(uri2);
        ImageRequest[] requests = {request1, request2};

        DraweeController controller = Fresco.newDraweeControllerBuilder()
                .setFirstAvailableImageRequests(requests)
                .setOldController(sdvFrescoMulti.getController())
                .build();

        sdvFrescoMulti.setController(controller);
    }

        8.圖片加載監聽

                1)佈局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_fresco_listener"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include layout="@layout/titlebar"></include>

    <com.facebook.drawee.view.SimpleDraweeView
        android:layout_gravity="center"
        android:id="@+id/sdv_fresco_listener"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_marginTop="48dp"
        fresco:placeholderImage="@drawable/atguigu_logo" />

    <Button
        android:id="@+id/bt_fresco_listener"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="48dp"
        android:text="開始加載圖片" />

    <TextView
        android:id="@+id/tv_fresco_listener"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="@android:color/black"
        android:textSize="14sp" />

    <TextView
        android:id="@+id/tv_fresco_listener2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="@android:color/black"
        android:textSize="14sp" />
</LinearLayout>

                2)代碼

                        a)正常加載圖片

     @OnClick(R.id.bt_fresco_listener)
    void bt_fresco_listener_click(View view) {

        ProgressiveJpegConfig jpegConfig = new ProgressiveJpegConfig() {
            @Override
            public int getNextScanNumberToDecode(int scanNumber) {
                return scanNumber + 2;
            }

            @Override
            public QualityInfo getQualityInfo(int scanNumber) {
                boolean isGoodEnough = (scanNumber >= 5);

                return ImmutableQualityInfo.of(scanNumber, isGoodEnough, false);
            }
        };

        ImagePipelineConfig.newBuilder(this).setProgressiveJpegConfig(jpegConfig).build();
        Uri uri = Uri.parse("http://h.hiphotos.baidu.com/zhidao/pic/item/58ee3d6d55fbb2fbac4f2af24f4a20a44723dcee.jpg");
        ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri).setProgressiveRenderingEnabled(true).build();

        DraweeController controller = Fresco.newDraweeControllerBuilder()
                .setOldController(sdvFrescoListener.getController())
                .setImageRequest(request)
                //設置監聽器監聽圖片加載狀態
                .setControllerListener(controllerListener)
                .build();

        sdvFrescoListener.setController(controller);
    }

                        b)加載過程監聽

    //對所有的圖片加載,onFinalImageSet 或者 onFailure 都會被觸發。前者在成功時,後者在失敗時。
    //如果允許呈現漸進式JPEG,同時圖片也是漸進式圖片,onIntermediateImageSet會在每個掃描被解碼後回調。
    // 具體圖片的那個掃描會被解碼,參見漸進式JPEG圖
    private ControllerListener controllerListener = new BaseControllerListener<ImageInfo>() {
        @Override
        public void onFinalImageSet(String id, ImageInfo imageInfo, Animatable animatable) {
            super.onFinalImageSet(id, imageInfo, animatable);

            if (imageInfo == null) {
                return;
            }

            QualityInfo qualityInfo = imageInfo.getQualityInfo();

            tvFrescoListener.setText("Final image received! " +
                    "\nSize: " + imageInfo.getWidth()
                    + "x" + imageInfo.getHeight()
                    + "\nQuality level: " + qualityInfo.getQuality()
                    + "\ngood enough: " + qualityInfo.isOfGoodEnoughQuality()
                    + "\nfull quality: " + qualityInfo.isOfFullQuality());
        }

        @Override
        public void onIntermediateImageSet(String id, ImageInfo imageInfo) {
            super.onIntermediateImageSet(id, imageInfo);

            tvFrescoListener2.setText("IntermediateImageSet image receiced");
        }

        @Override
        public void onFailure(String id, Throwable throwable) {
            super.onFailure(id, throwable);

            tvFrescoListener.setText("Error loading" + id);
        }
    };

        9.圖片縮放和旋轉

                1)佈局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_fresco_resize"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include layout="@layout/titlebar"></include>

    <com.facebook.drawee.view.SimpleDraweeView
        android:layout_gravity="center"
        android:id="@+id/sdv_fresco_resize"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_marginTop="48dp"
        fresco:placeholderImage="@drawable/atguigu_logo" />

    <Button
        android:id="@+id/bt_fresco_resize"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="48dp"
        android:text="修內存中改圖片大小" />

    <Button
        android:id="@+id/bt_fresco_rotate"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="旋轉圖片" />

</LinearLayout>

                2)代碼

                        a)縮放

    @OnClick(R.id.bt_fresco_resize)
    void bt_fresco_resize_click(View view) {

        int width = 50;
        int height = 50;

        Uri uri = Uri.parse("http://c.hiphotos.baidu.com/image/pic/item/962bd40735fae6cd21a519680db30f2442a70fa1.jpg");

        ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
                .setResizeOptions(new ResizeOptions(width, height)).build();

        PipelineDraweeController controller = (PipelineDraweeController) Fresco.newDraweeControllerBuilder()
                .setOldController(sdvFrescoResize.getController())
                .setImageRequest(request)
                .build();

        sdvFrescoResize.setController(controller);
    }

                        b)旋轉

    @OnClick(R.id.bt_fresco_rotate)
    void bt_fresco_rotate_click(View view) {

        Uri uri2 = Uri.parse("http://c.hiphotos.baidu.com/image/pic/item/962bd40735fae6cd21a519680db30f2442a70fa1.jpg");

        ImageRequest request1 = ImageRequestBuilder.newBuilderWithSource(uri2)
                .setAutoRotateEnabled(true).build();

        DraweeController controller1 = Fresco.newDraweeControllerBuilder()
                .setImageRequest(request1)
                .setOldController(sdvFrescoResize.getController()).build();

        sdvFrescoResize.setController(controller1);
    }

        10.修改圖片

                1)佈局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_fresco_modify"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include layout="@layout/titlebar"></include>

    <com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/sdv_fresco_modify"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_gravity="center"
        android:layout_marginTop="48dp"
        fresco:placeholderImage="@drawable/atguigu_logo" />

    <Button
        android:id="@+id/bt_fresco_modify"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="48dp"
        android:text="爲圖片添加網格" />
</LinearLayout>

                2)代碼

     @OnClick(R.id.bt_fresco_modify)
    void bt_fresco_modify_click(View view){

        Uri uri = Uri.parse("http://c.hiphotos.baidu.com/image/pic/item/962bd40735fae6cd21a519680db30f2442a70fa1.jpg");

        Postprocessor redMeshPostprocessor = new BasePostprocessor() {
            @Override
            public String getName() {
                return "redMeshPostprocessor";
            }

            //繪製紅色點狀網格
            @Override
            public void process(Bitmap bitmap) {

                for (int x = 0; x < bitmap.getWidth(); x += 2) {

                    for (int y = 0; y < bitmap.getHeight(); y += 2) {
                        bitmap.setPixel(x, y, Color.RED);
                    }
                }
            }
        };

        ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
                .setPostprocessor(redMeshPostprocessor)
                .build();

        PipelineDraweeController controller = (PipelineDraweeController)
                Fresco.newDraweeControllerBuilder()
                        .setImageRequest(request)
                        .setOldController(sdvFrescoModify.getController())
                        .build();

        sdvFrescoModify.setController(controller);
    }

        11.動態展示圖片

                1)佈局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_fresco_auto_size"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include layout="@layout/titlebar"></include>

    <Button
        android:id="@+id/bt_fresco_loadsmall"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="加載圖片" />

    <LinearLayout
        android:id="@+id/ll_fresco"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:orientation="vertical">

    </LinearLayout>
</LinearLayout>

                2)代碼

simpleDraweeView = new SimpleDraweeView(this);
        simpleDraweeView.setAspectRatio(1.0f);


@OnClick(R.id.bt_fresco_loadsmall)
    void bt_fresco_loadsmall_click(View view) {

        final Uri uri = Uri.parse("http://img4q.duitang.com/uploads/item/201304/27/20130427043538_wAfHC.jpeg");


        ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
                .build();

        PipelineDraweeController controller = (PipelineDraweeController)
                Fresco.newDraweeControllerBuilder()
                        .setImageRequest(request)
                        .setOldController(simpleDraweeView.getController())
                        .build();

        simpleDraweeView.setController(controller);

        llFresco.addView(simpleDraweeView);
    }

     四、注意事項

            1.問題處理

                    1)重複的邊界

                                這是使用圓角的一個缺陷。 參考圓角和圓圈 來獲取更多信息。

                    2)圖片沒有加載

                                你可以從 image pipeline 打出的日誌來查看原因。 這裏提供一些通常會導致問題的原因。

                    3)文件不可用

                                無效的路徑、鏈接會導致這種情況。判斷網絡鏈接是否有效,你可以嘗試在瀏覽器中打開它,看看是否圖片會被加載。若圖片依然加載不出來,那麼這不是Fresco的問題。判斷本地文件是否有效,你可以通過下面這段代碼來校驗:

                                如果這裏拋出了異常,那麼這不是Fresco的問題,可能是你的其他代碼導致的。有可能是沒有獲取到SD卡讀取權限、路徑不合法、文件不存在等。

FileInputStream fis = new FileInputStream(new File(localUri.getPath()));

                    4)OOM - 無法分配圖片空間

                                加載特別特別大的圖片時最容易導致這種情況。如果你加載的圖片比承載的View明顯大出太多,那你應該考慮將它Resize一下。

                    5)Bitmap太大導致無法繪製

                                  Android 無法繪製長或寬大於2048像素的圖片。這是由OpenGL渲染系統限制的,如果它超過了這個界限,Fresco會對它進行Resize。

                    6)通過Logcat來判斷原因

                                在加載圖片時會出現各種各樣的原因導致加載失敗。 在使用Fresco的時候,最直接的方式就是查看 image pipeline 打出的VERBOSE級別日誌。

                    7)啓動日誌

                                默認情況下Fresco是關閉日誌輸出的,你可以配置image pipeline讓它啓動。

Set<RequestListener> requestListeners = new HashSet<>();
requestListeners.add(new RequestLoggingListener());
ImagePipelineConfig config = ImagePipelineConfig.newBuilder(context)
   // other setters
   .setRequestListeners(requestListeners)
   .build();
Fresco.initialize(context, config);
FLog.setMinimumLoggingLevel(FLog.VERBOSE);

                    8)查看日誌

                                你可以通過下面這條shell命令來查看Fresco日誌:

adb logcat -v threadtime | grep -iE 'LoggingListener|AbstractDraweeController|BufferedDiskCache'

圖片如果沒有在內存緩存中找到,也沒有在磁盤緩存中找到,最後去網絡上下載圖片。下載成功後,圖片被解碼,之後請求結束。最後數據源通知 controller 圖片就緒,顯示圖片(set_final_result)。

            2.一些陷阱

                     1)不要使用 ScrollViews

                                如果你想要在一個長的圖片列表中滑動,你應該使用 RecyclerView,ListView,或 GridView。這三者都會在你滑動時不斷重用子視圖。Fresco 的 view 會接收系統事件,使它們能正確管理內存。
ScrollView 不會這樣做。因此,Fresco view 不會被告知它們是否在屏幕上顯示,並保持圖片內存佔用直到你的 Fragment 或 Activity 停止。你的 App 將會面臨更大的 OOM 風險。

                    2)不要向下轉換

                                不要試圖把Fresco返回的一些對象進行向下轉化,這也許會帶來一些對象操作上的便利,但是也許在後續的版本中,你會遇到一些因爲向下轉換特性丟失導致的難以處理的問題。

                    3)不要使用getTopLevelDrawable

                                  DraweeHierarchy.getTopLevelDrawable() 僅僅 應該在DraweeViews中用,除了定義View中,其他應用代碼建議連碰都不要碰這個。在自定義view中,也千萬不要將返回值向下轉換,也許下個版本,我們會更改這個返回值類型。

                    4)不要複用 DraweeHierarchies

                                永遠不要把 DraweeHierarchy 通過 DraweeView.setHierarchy 設置給不同的View。DraweeHierarchy 是由一系列 Drawable 組成的。在 Android 中, Drawable 不能被多個 View 共享。

                    5)不要在多個DraweeHierarchy中使用同一個Drawable

                            原因同上。不過你可以在佔位圖、重試圖、錯誤圖中使用相同的資源ID,Android 實際會創建不同的 Drawable。 如果你使用GenericDraweeHierarchyBuilder,那麼需要調用Resources.getDrawable來通過資源獲取圖片。不過請不要只調用一次然後將結果傳給不同的Hierarchy!

                    6)不要直接控制 hierarchy

                                    不要直接使用 SettableDraweeHierarchy 方法(reset,setImage,…)。它們應該僅由 controller 使用。不要使用setControllerOverlay來設置一個覆蓋圖,這個方法只能給 controller 調用。如果你需要顯示覆蓋圖,可以參考Drawee的各種效果配置

                    7)不要直接給 DraweeView 設置圖片

                                目前 DraweeView 直接繼承於 ImageView,因此它有 setImageBitmap,
setImageDrawable 等方法。
如果利用這些方法直接設置一張圖片,內部的 DraweeHierarchy 就會丟失,也就無法取到image
pipeline 的任何圖像了。

                    8)使用 DraweeView 時,請不要使用任何 ImageView 的屬性

                            在後續的版本中,DraweeView 會直接從 View 派生。任何屬於 ImageView 但是不屬於 View 的方法都會被移除。

            3.爲什麼不支持wrap_content

                    人們經常會問,爲什麼Fresco中不可以使用wrap_content?主要的原因是,Drawee永遠會在getIntrinsicHeight/getIntrinsicWidth中返回-1。這麼做的原因是 Drawee 不像ImageView一樣。它同一時刻可能會顯示多個元素。比如在從佔位圖漸變到目標圖時,兩張圖會有同時顯示的時候。再比如可能有多張目標圖片(低清晰度、高清晰度兩張)。如果這些圖像都是不同的尺寸,那麼很難定義”intrinsic”尺寸。
如果我們要先用佔位圖的尺寸,等加載完成後再使用真實圖的尺寸,那麼圖片很可能顯示錯誤。它可能會被根據佔位圖的尺寸來縮放、裁剪。唯一防止這種事情的方式就只有在圖片加載完成後強制觸發一次layout。這樣的話不僅會影響性能,而且會讓應用的界面突變,很影響用戶體驗!如果用戶正在讀一篇文章,然後在圖片加載完成後整篇文章突然向下移動,這是非常不好的。
所以你必須指定尺寸或者用match_parent來佈局。你如果從服務端請求圖片,服務端可以做到返回圖片尺寸。然後你拿到之後通過setLayoutParams 來給View設置寬高。當然如果你必須要使用wrap_content,那麼你可以參考StackOverflow上的一個回答。但是我們以後會移除這個功能,Ugly things should look ugly。

            4.共享元素動畫

                    使用 ChangeBounds,而不是ChangeImageTransform
Android 5.0 (Lollipop) 引入了 共享元素動畫,允許在多個Activity切換時共享相同的View!
你可以在XML中定義這個變換。有個ChangeImageTransform變換可以在共享元素切換時對ImageView進行變換,可惜Fresco暫時不支持它,因爲Drawee維護着自己的轉換Matrix。

幸運的是你可以有另一種做法:使用ChangeBounds。你可以改變layout的邊界,這樣Fresco會根據它進行自適應,也能夠達到你想要的功能。

            當你如果認真看到這裏,那我爲您的耐心點贊。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章