• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • 第三方庫之—Glide的使用

    Glide的使用

    Glide是我使用最久,也是最喜歡的一款第三方圖片加載框架,以前只是使用,也沒有做系統性的總結,現在開始重新整理一遍這些優秀的第三方框架。
    Glide官方地址:

    Glide的相關方法:

    • with:指定了聲明周期
    • load():加載資源,String/Uri/File/Integer/URL/byte[]/T,或者 loadFromMediaStore(Uri uri)
    • placeholder(resourceId/drawable): 設置資源加載過程中的占位Drawable。
    • error():load失敗時顯示的Drawable。
    • override() :調整圖片大小
    • centerCrop():圖片裁剪,ImageView 可能會完全填充,但圖像可能不會完整顯示。
    • fitCenter(): 圖像裁剪,圖像將會完全顯示,但可能不會填滿整個 ImageView。
    • animate(): 指定加載動畫。
    • crossFade()/crossFade(int duration):imageView改變時的動畫,version 3.6.1后默認開啟300毫秒
    • dontAnimate():移除所有的動畫。
    • transform():圖片轉換。
    • bitmapTransform(): bitmap轉換,不可以和(centerCrop() 或 fitCenter())共用。
    • priority(Priority priority):當前線程的優先級,Priority.IMMEDIATE,Priority.HIGH,Priority.NORMAL(default),Priority.LOW
    • thumbnail(): 縮略圖.
    • listener():異常監聽
    • preload(int width, int height): 預加載resource到緩存中(單位為pixel)
    • fallback(Drawable drawable):設置model為空時顯示的Drawable。
    • using() :為單個的請求指定一個 model
    • asGif():Gif 檢查,如果是圖片且加了判斷,則會顯示error占位圖,否則會顯示圖片
    • asBitmap():bitmap轉化,如果是gif,則會顯示第一幀
    • .skipMemoryCache(true) 禁止緩存
    • .diskCacheStrategy(DiskCacheStrategy.NONE)禁止磁盤緩存

      Glide 可以以load(File)的形式播放本地視頻,但是如果需要播放網絡視屏,則要用VideoView


    緩存策略

    一張圖片變化特別快的時候,應該禁止緩存
    .skipMemoryCache(true)
    即使關閉內存緩存,請求圖片將會仍然被存儲在設備的磁盤緩存中,如果一張圖片變化很快,仍需要禁止磁盤緩存
    .diskCacheStrategy(DiskCacheStrategy.NONE)
    Glide 緩存了原始圖像,全分辨率圖像和另外小版本的圖像,因此禁用磁盤緩存是用枚舉來控制的
    DiskCacheStrategy.NONE //什么都不緩存,就像剛討論的那樣
    DiskCacheStrategy.SOURCE //僅僅只緩存原來的全分辨率的圖像。在我們上面的例子中,將會只有一個 1000x1000 像素的圖片
    DiskCacheStrategy.RESULT //僅僅緩存最終的圖像,即,降低分辨率后的(或者是轉換后的)
    DiskCacheStrategy.ALL //緩存所有版本的圖像(默認行為)

    自定義緩存

    磁盤緩存,用類DiskLruCacheWrapper來設置目錄
    builder.setDiskCache(new DiskCache.Factory() {
                @Override
                public DiskCache build() {
                // 自己的緩存目錄
                    File imgFile = new File(Environment.getExternalStorageDirectory()+"/Android/data/package-name");
                    return DiskLruCacheWrapper.get(imgFile,DiskCache.Factory.DEFAULT_DISK_CACHE_SIZE);
                }
            });
    內存緩存,用類Memory Cache 來設置大小
    MemorySizeCalculator calculator = new MemorySizeCalculator(context); 
    builder.setMemoryCache(new LruResourceCache(calculator.getMemoryCacheSize()));

    Bitmap Pool

    重復使用及銷毀策略。設置方法:GlideBuilder.setBitmapPool() 默認采用的是LruBitmapPool,使用了LRU算法。
    MemorySizeCalculator calculator = new MemorySizeCalculator(context);
    int defaultBitmapPoolSize = calculator.getBitmapPoolSize();
    int customBitmapPoolSize = (int) (1.2 * defaultBitmapPoolSize);
    builder.setBitmapPool( new LruBitmapPool( customBitmapPoolSize );

    Bitmap Format

    Bitmap Format用于設置全局缺省首選Bitmap規格,設置方法:GlideBuilder.setDecodeFormat() 默認采用RGB_565(比ARGB_8888節省一半的內存),但不支持透明度。

    優先級

    會發現優先級高的先 顯示出來,即使圖片比較大。
    //優先加載
        Glide
            .with(context)
            .load(heroImageUrl)
            .priority(Priority.HIGH)
            .into(imageViewHero);
        //后加載
        Glide
            .with(context)
            .load(itemImageUrl)
            .priority(Priority.LOW)
            .into(imageViewItem);
    先顯示縮略圖,后顯示原圖
     //用原圖的1/10作為縮略圖
    Glide
            .with(this)
            .load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png")
            .thumbnail(0.1f)
            .into(iv_0);
        //用其它圖片作為縮略圖
        DrawableRequestBuilder<Integer> thumbnailRequest = Glide
            .with(this)
            .load(R.drawable.news);
        Glide.with(this)
            .load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png")
            .thumbnail(thumbnailRequest)
            .into(iv_0);

    圖片處理

    裁剪、模糊、濾鏡等。可以使用 **wasabeef/glide-transformations** , 實現Transformation 接口,或者使用抽象類BitmapTransformation, 通過transform()或bitmapTransform()來處理圖片
    //圓形裁剪
    Glide.with(this)
        .load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png")
        .bitmapTransform(new CropCircleTransformation(this))
        .into(iv_0);
    //圓角處理
    Glide.with(this)
        .load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png")
        .bitmapTransform(new RoundedCornersTransformation(this,30,0, RoundedCornersTransformation.CornerType.ALL))
        .into(iv_0);
    //灰度處理
    Glide.with(this)
        .load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png")
        .bitmapTransform(new GrayscaleTransformation(this))
        .into(iv_0);
    //模糊處理
    Glide.with(this).load(R.drawable.demo)
            .bitmapTransform(new BlurTransformation(context))
            .into((ImageView) findViewById(R.id.image));
    //其它變換...
    

    自定義轉換

    public class BlurTransformation extends BitmapTransformation {
    
        public BlurTransformation(Context context) {
            super( context );
        }
    
        @Override
        protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
            return null; // todo
        }
    
        @Override
        public String getId() {
            return null; // todo
        }
    }
    其中getId() :描述了這個轉換的唯一標識符,將作為緩存系統的一部分 可以使用單種轉換和多種轉換,如多種轉換:
    Glide  
        .with( context )
        .load( eatFoodyImages[1] )
        .transform( new GreyscaleTransformation( context ), new BlurTransformation( context ) )
        .into( imageView2 );

    回調 Target

    SimpleTarget target 泛型:Bitmap,GlideDrawable,GifDrawable 其中使用字段聲明target’而不是使用匿名內部類的形式,可以避免被垃圾回收機制回收,而回調為空的現象。
    private SimpleTarget target = new SimpleTarget<Bitmap>() {  
        @Override
        public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {
            // do something with the bitmap
            // for demonstration purposes, let's just set it to an ImageView
            imageView1.setImageBitmap( bitmap );
        }
    };
    
    private void loadImageSimpleTarget() {  
        Glide
            .with( context ) // could be an issue!
            .load( eatFoodyImages[0] )
            .asBitmap()
            .into( target );
    }

    Target生命周期

    with( context ):關系到生命周期。如果請求需要在 activity 生命周期之外去做時,需要使用:
    private void loadImageSimpleTargetApplicationContext() {  
        Glide
            .with( context.getApplicationContext() ) // safer!
            .load( eatFoodyImages[1] 
            .asBitmap()
            .into( target2 );
    }

    Target 指定尺寸

    使用ImageView 作為參數給 .into()的時候,Glide 會用 ImageView 的大小去限制圖像的大小 但是target并沒有已知的大小,如果知道圖片大小則應指出,減少內存消耗。
    private SimpleTarget target2 = new SimpleTarget<Bitmap>( 250, 250 ) {  
        @Override
        public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {
            imageView2.setImageBitmap( bitmap );
        }
    };
    
    private void loadImageSimpleTargetApplicationContext() {  
        Glide
            .with( context.getApplicationContext() ) // safer!
            .load( eatFoodyImages[1] )
            .asBitmap()
            .into( target2 );
    }

    ViewTarget

    常用于自定以控件中,比如自定義控件中組合了ImageView控件,如下 public class FutureStudioView extends FrameLayout { ImageView iv; TextView tv;
    public void initialize(Context context) {
            inflate( context, R.layout.custom_view_futurestudio, this );
    
            iv = (ImageView) findViewById( R.id.custom_view_image );
            tv = (TextView) findViewById( R.id.custom_view_text );
        }
    
        public FutureStudioView(Context context, AttributeSet attrs) {
            super( context, attrs );
            initialize( context );
        }
    
        public FutureStudioView(Context context, AttributeSet attrs, int defStyleAttr) {
            super( context, attrs, defStyleAttr );
            initialize( context );
        }
    
        public void setImage(Drawable drawable) {
            iv = (ImageView) findViewById( R.id.custom_view_image );
    
            iv.setImageDrawable( drawable );
        }
    }
    使用如下方法給自定義控件中的ImageView設置圖片
    private void loadImageViewTarget() {  
        FutureStudioView customView = (FutureStudioView) findViewById( R.id.custom_view );
    
        //傳遞了參數 customView
        viewTarget = new ViewTarget<FutureStudioView, GlideDrawable>( customView ) {
            @Override
            public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
            //調用了FutureStudioView的setImage方法
                this.view.setImage( resource.getCurrent() );
            }
        };
    
        Glide
            .with( context.getApplicationContext() ) // safer!
            .load( eatFoodyImages[2] )
            .into( viewTarget );
    }

    NotificationTarget

    用于加載圖片到通知欄和應用小部件中的

    動畫

    animate() :可以加載資源文件animate.xml文件 或者 屬性動畫: - ViewPropertyAnimation - ViewAnimation - NoAnimation - DrawableCrossFadeViewAnimation
    ViewPropertyAnimation.Animator animationObject = new ViewPropertyAnimation.Animator() {  
        @Override
        public void animate(View view) {
            // if it's a custom view class, cast it here
            // then find subviews and do the animations
            // here, we just use the entire view for the fade animation
            view.setAlpha( 0f );
    
            ObjectAnimator fadeAnim = ObjectAnimator.ofFloat( view, "alpha", 0f, 1f );
            fadeAnim.setDuration( 2500 );
            fadeAnim.start();
        }
    };
    
    Glide  
        .with( context )
        .load( eatFoodyImages[1] )
        .animate( animationObject )
        .into( imageView2 );

    Glide module

    Glide module 是一個抽象方法,全局改變 Glide 行為的一個方式。 前面單策略的定義中都用到了GlideBuilder類 如果你需要訪問 GlideBuilder,你需要去實現一個 GlideModule 接口的公共類
    public class FileGlideModule  implements GlideModule{
        @Override
        public void applyOptions(final Context context, GlideBuilder builder) {
    //builder 內的所有方法你都可以設置。
    //        builder.setDiskCache(new InternalCacheDiskCacheFactory(context));
            builder.setDiskCache(new ExternalCacheDiskCacheFactory(context));
          /*  builder.setDiskCache(new DiskCache.Factory() {
                @Override
                public DiskCache build() {
                    File imgFile = new File(Environment.getExternalStorageDirectory()+"/Android/data/com.leying365");
                    return DiskLruCacheWrapper.get(imgFile,DiskCache.Factory.DEFAULT_DISK_CACHE_SIZE);
                }
            });*/
            MemorySizeCalculator calculator = new MemorySizeCalculator(context);
            builder.setMemoryCache(new LruResourceCache(calculator.getMemoryCacheSize()));
            builder.setBitmapPool(new LruBitmapPool(calculator.getBitmapPoolSize()));
            builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);
        }
    
        @Override
        public void registerComponents(Context context, Glide glide) {
    
        }
    }
    最終通過 來生效 常用方法:
    • setMemoryCache(MemoryCache memoryCache)
    • setBitmapPool(BitmapPool bitmapPool)
    • setDiskCache(DiskCache.Factory diskCacheFactory)
    • setDiskCacheService(ExecutorService service)
    • setResizeService(ExecutorService service)
    • setDecodeFormat(DecodeFormat decodeFormat)

    網絡庫

    Glide 使用ModeLoader 接口來 集成網絡庫,Glide提供了兩種網絡庫 的實現,分別為OkHttp 和 Volley。

    在build.gradle中添加如下依賴,glide會默認使用OKhttp來做所有的網絡連接

    dependencies {  
        // your other dependencies
        // ...
    
        // Glide
        compile 'com.github.bumptech.glide:glide:3.7.0'
    
        // Glide's OkHttp Integration 
        compile 'com.squareup.okhttp3:okhttp:3.2.0'
        compile 'com.squareup.okhttp3:logging-interceptor:3.2.0'
    }

    上面會將必要的GlideModule 到你的 Android.Manifest中。

    緩存與失效機制

    Glide 通過 url、viewwidth、viewheight、屏幕的分辨率等以一種散列算法生成一個獨有、安全的文件名作為key保存到disk上.因為其是通過一個散列算法來實現的,因此很難定位文件的緩存,幸好Glide提供了signature()方法允許將一個附加的數據加入到緩存key當中,可以用來保證緩存的及時性.

    系統默認實現了MediaStoreSignature,StringSignature.

    Glide.with(fragment)
        .load(mediaStoreUri)
        .signature(new MediaStoreSignature(mimeType, dateModified, orientation))
        .into(view);

    當然也可以自己來實現Signature

    public class MSignature implements Key {
    
        @Override
        public boolean equals(Object o) {
         //...
        }
        @Override
        public int hashCode() {
           //...
        }
        @Override
        public void updateDiskCacheKey(MessageDigest messageDigest) {
            messageDigest.update(ByteBuffer.allocate(Integer.SIZE)
    .putInt(signature).array());
        }
    }

    極端情況,不緩存可以用diskCacheStrategy(DiskCacheStrategy.NONE.)來實現

    圖片下載

    Glide除了提供into方法來加載圖片外,也提供了downloadOnly方法來實現圖片下載.

    FutureTarget<File> future = Glide.with(applicationContext)
        .load(yourUrl)
        .downloadOnly(500, 500);
    File cacheFile = future.get();

    下載之后可以通過如下方式來加載圖片

    Glide.with(yourFragment)
        .load(yourUrl)
        //DiskCacheStrategy.ALL或者DiskCacheStrategy.SOURCE可以保證程序會先去讀緩存文件
        .diskCacheStrategy(DiskCacheStrategy.ALL)
        .into(yourView);

    如果想獲取一張圖片的Bitmap,可以使用如下方式

    //此方法需要try/catch處理,并且最好在子線程中,否則會阻塞主線程

    Bitmap myBitmap = Glide.with(applicationContext)
        .load(yourUrl)
        .asBitmap()
        .centerCrop()
        //設置大小
        .into(500, 500)
        .get()

    圖片模糊處理

    這里寫圖片描述
    使用Glide加載圖片,將模糊圖片設置為背景,代碼如下:

    Glide.with(this).load(mImageCover)
                            .asBitmap()
                            .into(new SimpleTarget<Bitmap>() {
                                @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
                                @Override
                                public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
                                    blur(resource,ivCover,24);
                                    ivCover.setImageBitmap(resource);
                                }
                            });

    //blur方法,將圖片模糊處理添加到背景中

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
        private void blur(Bitmap bkg, View view, float radius) {
            /*view.getMeasuredWidth(),
                    view.getMeasuredHeight(),*/
            Bitmap overlay = Bitmap.createBitmap(
                    bkg.getWidth(),
                    bkg.getHeight(),
                    Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(overlay);
            canvas.drawBitmap(bkg, -view.getLeft(),
                    -view.getTop(), null);
            RenderScript rs = RenderScript.create(this);
            Allocation overlayAlloc = Allocation.createFromBitmap(
                    rs, overlay);
            ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create(
                    rs, overlayAlloc.getElement());
            blur.setInput(overlayAlloc);
            blur.setRadius(radius);
            blur.forEach(overlayAlloc);
            overlayAlloc.copyTo(overlay);
            view.setBackground(new BitmapDrawable(
                    getResources(), overlay));
            rs.destroy();
        }

    //圖片模糊類,使用方法如下:

    /*BlurBuilder builder = new BlurBuilder();
            Bitmap bitmap = builder.blur(this, bmp);
            image.setImageBitmap(bitmap);*/
    public class BlurBuilder {
        private static final float BITMAP_SCALE = 0.2f;
        private static final float BLUR_RADIUS = 8.75f;
        public static Bitmap blur(Context context, Bitmap image) {
            int width = Math.round(image.getWidth() * BITMAP_SCALE);
            int height = Math.round(image.getHeight() * BITMAP_SCALE);
            Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);
            Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);
            RenderScript rs = RenderScript.create(context);
            ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
            Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
            Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
            theIntrinsic.setRadius(BLUR_RADIUS);
            theIntrinsic.setInput(tmpIn);
            theIntrinsic.forEach(tmpOut);
            tmpOut.copyTo(outputBitmap);
            return outputBitmap;
        }
    }

    裁剪、模糊、濾鏡等。可以使用 wasabeef/glide-transformations

    版權聲明:本文為qq_32175491原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/qq_32175491/article/details/72637953

    智能推薦

    第三方庫pymysql

    python在操作mysql數據庫最常用的第三方庫是pymysql,使用該模塊需要使用pip工具進行安裝。     如果已經安裝就會顯示已經安裝,也可以通過pip list命令來是否安裝 安裝以后,安裝mysql數據庫服務器,可在該頁面根據相應的操作系統https://dev.mysql.com/downloads/下載安裝包進行安裝,安裝過程請自行百度,這里不做介紹。 安裝完...

    python第三方庫

    概述 系統標準庫是安裝Python解釋器時,自帶安裝的一些最基本最常用的的Python類庫,它們的位置是:解釋器安裝目錄/Lib/; 光有系統標準庫是遠遠不能滿足多樣化的開發需求的,我們還常常要使用到一些第三方類庫,它們的位置是:解釋器安裝目錄/Lib/site-packages/; 安裝第三方類庫: Python解釋器自帶一個包管理工具pip.exe,它的位置是:解釋器安裝目錄/Scripts/...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    猜你喜歡

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    統計學習方法 - 樸素貝葉斯

    引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...

    styled-components —— React 中的 CSS 最佳實踐

    https://zhuanlan.zhihu.com/p/29344146 Styled-components 是目前 React 樣式方案中最受關注的一種,它既具備了 css-in-js 的模塊化與參數化優點,又完全使用CSS的書寫習慣,不會引起額外的學習成本。本文是 styled-components 作者之一 Max Stoiber 所寫,首先總結了前端組件化樣式中的最佳實踐原則,然后在此基...

    精品国产乱码久久久久久蜜桃不卡