android Glide簡單使用

 

版權聲明:你們能夠轉載,請寫明轉載申明 https://blog.csdn.net/bzlj2912009596/article/details/81702367

今天,簡單講講Android裏Glide的簡單使用。css

 

Android框架系列:html

一.android EventBus的簡單使用java

二.android Glide簡單使用android

 

對於Glide這個加載圖片的框架,不少人都在用,我以前使用的是ImageLoader,最近查資料時,發現Glide纔是Google推薦的加載圖片框架,功能很是強大,並且還有Google專人維護,要知道,ImageLoader已經沒人維護了,除了問題可沒人解答。因此有必要整理一下Glide的使用。git

Glide是谷歌爲咱們推薦的一個圖片加載庫。爲何要選擇使用Glide呢?github

  • 一、代碼有人維護,不至於出現問題,項目組都搞不定的時候問題沒法解決。(ImageLoader已沒人維護了)
  • 二、代碼簡潔,可讀性很好。(Fresco是一個很是優秀的庫,可是配置稍顯麻煩,同時代碼風格讀起來有些生疏)
  • 三、功能強大(400多k的包,包含不少功能,例如:像加載Gif圖片就是Picasso作不到的)

下面咱們就來介紹下Glide的用法:緩存

Glide的基本使用

導入庫

compile 'com.github.bumptech.glide:glide:3.7.0'

添加代碼混淆(可加可不加)

  1.  
    -keep public class * implements com.bumptech.glide.module.GlideModule
  2.  
    -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
  3.  
    **[] $VALUES;
  4.  
    public *;
  5.  
    }
  6.  
     
  7.  
    # for DexGuard only
  8.  
    -keepresourcexmlelements manifest/application/meta- data@value=GlideModule

這個別忘了,不要粗心哦,很容易忘得,最簡單的問題,每每須要最簡單的搞定啦。網絡

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

簡單使用例子

  1.  
    // For a simple view:
  2.  
    @Override
  3.  
    public void onCreate(Bundle savedInstanceState) {
  4.  
    ...
  5.  
    ImageView imageView = (ImageView) findViewById(R.id.my_image_view);
  6.  
     
  7.  
    Glide.with( this).load("http://goo.gl/gEgYUd").into(imageView);
  8.  
    }
  9.  
     
  10.  
    // For a simple image list:
  11.  
    @Override
  12.  
    public View getView(int position, View recycled, ViewGroup container) {
  13.  
    final ImageView myImageView;
  14.  
    if (recycled == null) {
  15.  
    myImageView = (ImageView) inflater.inflate(R.layout.my_image_view, container, false);
  16.  
    } else {
  17.  
    myImageView = (ImageView) recycled;
  18.  
    }
  19.  
     
  20.  
    String url = myUrls.get(position);
  21.  
     
  22.  
    Glide
  23.  
    .with(myFragment)
  24.  
    .load(url)
  25.  
    .centerCrop()
  26.  
    .placeholder(R.drawable.loading_spinner)
  27.  
    .crossFade()
  28.  
    .into(myImageView);
  29.  
     
  30.  
    return myImageView;
  31.  
    }

Glide使用詳解

加載網絡圖片

Glide.with(context).load(internetUrl).into(targetImageView);

從文件加載圖片

  1.  
    File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),"Test.jpg");
  2.  
    Glide. with(context).load(file).into(imageViewFile);

從資源id加載圖片

  1.  
    int resourceId = R.mipmap.ic_launcher;
  2.  
    Glide. with(context).load(resourceId).into(imageViewResource);

從uri加載圖片

Glide.with(context).load(uri).into(imageViewUri);

播放本地mp4,只能是本地(獲取MP4視頻的縮略圖)

  1.  
    String filePath = "/storage/emulated/0/Pictures/example_video.mp4";
  2.  
    Glide. with( context ).load( Uri.fromFile( **new **File( filePath ) ) ).into( imageViewGifAsBitmap );

加載Gif圖片

  1.  
    String gifUrl = "xxxxx";
  2.  
    Glide. with( context ).load( gifUrl ).into( imageViewGif );

用bitMap播放Gif.asBitmap()

Glide.with( context ).load( gifUrl ).asBitmap().into( imageViewGifAsBitmap );

強制轉化爲Gif.asGif()

Glide.with( context ).load( gifUrl ).asGif().error( R.drawable.full_cake ).into( imageViewGif );

設置默認佔位圖.placeholder()

設置加載失敗的圖片.error()

Glide.with( context ).load( gifUrl ).placeholder( R.drawable.cupcake ).error( R.drawable.full_cake ).into( imageViewGif );

.fallback()

除了上面兩種‘異常狀況’,還有一種情形就是打開手機的通信錄的時候,能夠看到你給有些喜歡的人設置了照片,然而有些可憐的人並沒給有,總不能在那裏留下一片空白吧,這個時候至關於傳遞了Null,傳遞null時,這個callback方法就會被調用。app

  1.  
    Glide.with(context)
  2.  
    .load( null)//加載空指針的時候
  3.  
    .fallback( R.drawable.wuyanzu)
  4.  
    . into( imageViewNoFade );

設置加載動畫

其實這個是默認的,可是你仍是能夠寫出來,漸顯動畫
一、.crossFade() :Glide提供淡如淡出框架

Glide.with(context).load().placeholder(R.mipmap.ic_launcher) .error(R.mipmap.future_studio_launcher).crossFade().into(imageViewFade);

這裏還有一個.fadeFade(int duration),設置動畫時間。若是你不想要動畫能夠加上.dontAnimate()
二、.animate(android.R.anim.slide_in_left):Android系統提供,從左到右滑出加載動畫

調整圖片大小.resize(int ,int )

單位是像素,裁剪你的圖片大小。其實Glide已經會自動根據你ImageView裁剪照片來放在緩存中了。可是不想適應ImageView大小的時候,能夠調用這個方法.override()爲ImageView指定大小。

Glide.with(context).load(image).override(600, 200) .into(imageViewResize);

裁剪圖片.fitCenter().CenterCrop()

Glide清楚在合適的ImageView中加載合適的Image.當須要裁剪大小時,有個.centerCrop方法,這個方法的裁剪會讓你的ImageView周圍不會留白,還有一個.fitCenter()方法,表示讓你的Image徹底顯示,尺寸不對時,周圍會留白。

設置縮略圖.thumbnail()

.thumbnail()方法的目的就是讓用戶先看到一個低解析度的圖,點開後,再加載一個高解析度的圖。

  1.  
    //表示爲原圖的十分之一
  2.  
    Glide.with( context ).load(image).thumbnail( 0.1f ).into( imageView2 );

一種更高級的縮略圖加載方式:

當縮略圖也須要經過網絡加載所有解析度的時候。

  1.  
    private void loadImageThumbnailRequest() {
  2.  
    DrawableRequestBuilder< String> thumbnailRequest = Glide.with( context ).load( eatFoodyImages[2] );
  3.  
    Glide. with( context ).load( UsageExampleGifAndVideos.gifUrl ).thumbnail( thumbnailRequest ).into( imageView3 );
  4.  
    }

設置圖片顯示效果(圓角、圓形、高斯模糊、蒙板、裁剪等等).bitmapTransform()

  1.  
    Glide.with( this).load(R.mipmap.ic_image_sample)
  2.  
    //模糊
  3.  
    .bitmapTransform( new BlurTransformation(this))
  4.  
    //圓角
  5.  
    .bitmapTransform( new RoundedCornersTransformation(this, 24, 0, RoundedCornersTransformation.CornerType.ALL))
  6.  
    //遮蓋
  7.  
    .bitmapTransform( new MaskTransformation(this, R.mipmap.ic_launcher))
  8.  
    //灰度
  9.  
    .bitmapTransform( new GrayscaleTransformation(this))
  10.  
    //圓形
  11.  
    .bitmapTransform( new CropCircleTransformation(this))
  12.  
    . into(mResultIv);

除此以外還有實現諸如馬賽克、明暗度等更多濾鏡處理:

  • ToonFilterTransformation
  • SepiaFilterTransformation
  • ContrastFilterTransformation
  • InvertFilterTransformation
  • PixelationFilterTransformation
  • SketchFilterTransformation
  • SwirlFilterTransformation
  • BrightnessFilterTransformation
  • KuwaharaFilterTransformation
  • VignetteFilterTransformation

Glide的緩存

用過手機的都知道,當劃上劃下一個ListView的時候,第二次都比第一次快,就是由於爲GlideView對資源進行了緩存,並且封裝的很好,甚至不須要本身去設定緩存大小,Glide會智能地本身給咱們根據設備設置緩存大小。

緩存是爲了減小或者杜絕多的網絡請求。爲了不緩存,Glide用了內存緩存和‘外存緩存機制’,而且 提供了相應的方法,徹底封裝,不須要處理細節。Glide會自動緩存到內存,除非調用.skipMemoryCache( true )。儘管調用了這個,Glide仍是會緩存到外存,還有一種情形,就是有一張圖片,可是這張圖變化很是快,這個時候可能並不想緩存到外存中,就使用.diskCacheStrategy( DiskCacheStrategy.NONE )。若是你兩種都不須要,能夠兩個方法組合着一塊兒使用。

自定義外存緩存機制

Glide默認會緩存Image的不少個版本,好比原圖,若是你的imageView大小的緩存。.diskCacheStrategy()有如下幾種緩存策略:

  • DiskCacheStrategy.NONE 什麼都不緩存
  • DiskCacheStrategy.SOURCE 只緩存最高解析圖的image
  • DiskCacheStrategy.RESULT 緩存最後一次那個image,好比有可能你對image作了轉化
  • DiskCacheStrategy.ALL image的全部版本都會緩存
Glide.with( context ).load( image ).diskCacheStrategy( DiskCacheStrategy.SOURCE ).into( imageViewFile );

修改緩存大小、位置、加載圖片質量

和指定HttpClent爲OkHttp同樣,只不過咱們須要配置一些信息在applyOptions()函數裏面

  1.  
    public class GlideConfigModule implements GlideModule {
  2.  
    @Override
  3.  
    public void applyOptions(Context context, GlideBuilder builder) {
  4.  
    // 指定位置在packageName/cache/glide_cache,大小爲MAX_CACHE_DISK_SIZE的磁盤緩存
  5.  
    builder.setDiskCache( new InternalCacheDiskCacheFactory(context, "glide_cache", ConfigConstants.MAX_CACHE_DISK_SIZE));
  6.  
    //指定內存緩存大小
  7.  
    builder.setMemoryCache( new LruResourceCache(ConfigConstants.MAX_CACHE_MEMORY_SIZE));
  8.  
    //所有的內存緩存用來做爲圖片緩存
  9.  
    builder.setBitmapPool( new LruBitmapPool(ConfigConstants.MAX_CACHE_MEMORY_SIZE));
  10.  
    builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888); //和Picasso配置同樣
  11.  
    }
  12.  
     
  13.  
    @Override
  14.  
    public void registerComponents(Context context, Glide glide) {
  15.  
    }
  16.  
    }
  1.  
    <meta-data android:name= "com.example.imageloadpk.adapter.config.GlideConfigModule"
  2.  
    android: value="GlideModule"/>

通常的圖片加載框架設置了磁盤緩存和內存緩存就好了,可是Glide還設置了一個圖片緩存。
圖片緩存 <= 內存緩存

  1.  
    builder.setDiskCache( new InternalCacheDiskCacheFactory(context, "glide_cache", ConfigConstants.MAX_CACHE_DISK_SIZE));
  2.  
    //指定內存緩存大小
  3.  
    builder.setMemoryCache( new LruResourceCache(ConfigConstants.MAX_CACHE_MEMORY_SIZE));
  4.  
    //所有的內存緩存用來做爲圖片緩存
  5.  
    builder.setBitmapPool( new LruBitmapPool(ConfigConstants.MAX_CACHE_MEMORY_SIZE));

這裏Glide不只能夠緩存圖片,還能夠緩存其餘文件譬如視頻之類,也就是說能夠把他做爲咱們的緩存工具來使用,固然緩存方式仍是使用LRU。這樣咱們就沒必要再去從新集成LruCache和DiskLruCache,再去申請空間,配置。直接能夠複用Glide的。

使用緩存也加載動畫

可是,動畫默認是在圖片沒有緩存的狀況下才加載,想一想也是合理的,若是圖片已近下載到本地加載速度將會很是快,這個時候使用動畫過渡反而礙事。要讓從緩存中圖片呈現也加載動畫不能經過這種方式實現,能夠用監聽器來作。

  1.  
    private RequestListener<String, GlideBitmapDrawable> mAnimationRequestListener = new RequestListener<String, GlideBitmapDrawable>() {
  2.  
    @Override
  3.  
    public boolean onException(Exception e, String model, Target<GlideBitmapDrawable> target, boolean isFirstResource) {
  4.  
    return false;
  5.  
    }
  6.  
     
  7.  
    @Override
  8.  
    public boolean onResourceReady(GlideBitmapDrawable resource, String model, Target<GlideBitmapDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
  9.  
    dissProgress();
  10.  
    if (isFromMemoryCache) {
  11.  
    //若是是從緩存加載,設置動畫效果
  12.  
    mIvShow.setAnimation(AnimationUtils.loadAnimation(mContext, R.anim.scale));
  13.  
    }
  14.  
    //返回true表示攔截再也不傳遞,false表示事件會傳遞下去
  15.  
    return false;
  16.  
    }
  17.  
    };

請求優先級.priority()

加載圖片確定也是有前後順序,Glide提供了.priority()這個方法,它接收如下幾個參數:

  • Priority.LOW
  • Priority.NORMAL
  • Priority.HIGH
  • Priority.IMMEDIATE

可是Glide並不必定會按照你的順序來,只是儘可能按照你的順序來。(好比給一張很大的圖片最高的優先權,可是它並不必定比低優先級的圖先加載出來,這個時候只有使用縮略圖了)

  1.  
    Glide.with(mContext).load(Url.IMAGE_URL_TROCHILIDAE)
  2.  
    .priority(Priority.HIGH).into(mIvTonyRight);

利用callback在非標準狀況下加載圖片

上面全部的狀況都是加載圖片到ImageView中,可是並非全部的狀況都是這樣。譬如加載的控件類型不是ImageView,是個自定義的佈局。或者加載爲Background的形式。
可使用SimpleTarget類型,這裏指定他的大小爲500*100,加載爲背景圖片

  1.  
    .into( new SimpleTarget<Drawable>(500, 100) {
  2.  
    @Override
  3.  
    public void onResourceReady(Drawable resource, GlideAnimation<? super Drawable> glideAnimation) {
  4.  
    mBtnClear.setBackground(resource);
  5.  
    }

同理下載圖片原理是同樣

  1.  
    .into( new SimpleTarget<Bitmap>() {
  2.  
    @Override
  3.  
    public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
  4.  
    //toSave
  5.  
    Log.d(TAG, "onResourceReady: save successful");
  6.  
    }
  7.  
    });

Glide中的回調:Targets

從上面的介紹,已經能夠看出Glide內部封裝了全部的細節,什麼網絡請求,什麼緩存機制,當全部都就緒事後,自動切換回UI線程,更新ImageView。Targets就是Glide中的回調,當異步線程中全部的工做作完事後返回結果。說白了就是,當請求圖片完成後,須要回調的方法。

SimpleTarget

  1.  
    private SimpleTarget target = new SimpleTarget<Bitmap>() {
  2.  
    @Override
  3.  
    public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {
  4.  
    // do something with the bitmap
  5.  
    // for demonstration purposes, let's just set it to an ImageView
  6.  
    imageView1.setImageBitmap( bitmap );
  7.  
    }
  8.  
    };
  9.  
     
  10.  
    private void loadImageSimpleTarget() {
  11.  
    Glide.with( context ) * // could be an issue!*
  12.  
    .load( eatFoodyImages[ 0] )
  13.  
    .asBitmap() //強制Glide返回一個Bitmap
  14.  
    .into( target );
  15.  
    }

注意事項:

一、上面這段代碼不要寫成匿名內部類的機制,緣由就是java的自動垃圾回收機制可能在圖片尚未加載好的時候就已經把你的Target回收了。

二、注意.with()裏面的參數,Glide的請求是和傳進去的Context共存亡的,若是傳一個Activity進去,當Activity GC事後,你的請求也就GC了,可是若是這樣傳:.with(context.getApplicationContext() ).當你的Activity GC事後,請求仍是會繼續,回調仍是會繼續。
有size的Target

若是傳給into().的是一個ImageView,可是圖片的size比ImageView的Size打,Glide爲了節省時間,會加載小的那個size的Image。可是這對Target並不適用,覺得這裏並不知道SIze。可是若是知道image應該多大,能夠傳遞給Target.就像下面這樣:

  1.  
    private SimpleTarget target2 = new SimpleTarget<Bitmap>( 250, 250 ) {
  2.  
    @Override
  3.  
    public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {
  4.  
    imageView2.setImageBitmap( bitmap );
  5.  
    }
  6.  
    };
  7.  
     
  8.  
    private void loadImageSimpleTargetApplicationContext() {
  9.  
    Glide.with(context.getApplicationContext()); * // safer!*
  10.  
    .load( eatFoodyImages[ 1] )
  11.  
    .asBitmap()
  12.  
    .into( target2 );
  13.  
    }

ViewTarget

適用於想Glide加載到自定義View中去,

  1.  
    public class FutureStudioView extends FrameLayout {
  2.  
    ImageView iv;
  3.  
    TextView tv;
  4.  
     
  5.  
    public void nitialize(Context context) {
  6.  
    inflate( context, R.layout.custom_view_futurestudio, this );
  7.  
    iv = (ImageView) findViewById( R.id.custom_view_image );
  8.  
    tv = (TextView) findViewById( R.id.custom_view_text );
  9.  
    }
  10.  
     
  11.  
    public FutureStudioView(Context context, AttributeSet attrs) {
  12.  
    super( context, attrs );
  13.  
    initialize( context );
  14.  
    }
  15.  
     
  16.  
    public FutureStudioView(Context context,AttributeSet attrs,int defStyleAttr) {
  17.  
    super( context, attrs, defStyleAttr );
  18.  
    initialize( context );
  19.  
    }
  20.  
     
  21.  
    public void setImage(Drawable drawable) {
  22.  
    iv = (ImageView) findViewById( R.id.custom_view_image );
  23.  
    iv.setImageDrawable( drawable );
  24.  
    }
  25.  
    }

還有notificationTarget 和AppWidget做爲擴展自行研究嘍。

監聽器配置.listener()

  1.  
    Glide.with(getContext()).load(url)
  2.  
    .listener(mRequestListener) //配置監聽器
  3.  
    .placeholder(Drawables.sPlaceholderDrawable)
  4.  
    .error(Drawables.sErrorDrawable)
  5.  
    .into(mImageView);
  6.  
     
  7.  
    private RequestListener<String, GlideDrawable> mRequestListener = new RequestListener<String, GlideDrawable>() {
  8.  
    @Override
  9.  
    public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
  10.  
    //顯示錯誤信息
  11.  
    Log.w(TAG, "onException: ", e);
  12.  
    //打印請求URL
  13.  
    Log.d(TAG, "onException: " + model);
  14.  
    //打印請求是否還在進行
  15.  
    Log.d(TAG, "onException: " + target.getRequest().isRunning());
  16.  
    return false;
  17.  
    }
  18.  
     
  19.  
    @Override
  20.  
    public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
  21.  
    return false;
  22.  
    }
  23.  
    };

這裏的onException捕獲異常,若是返回true表示咱們本身處理掉了異常,false表示交給Glide去處理,由於咱們定義了.error()那麼就顯示error裏面的內容。

這裏onResourceReady表示是否準備資源顯示,返回true表示用戶本身已經設置好資源,包括截取操做,動畫操做之類的,準備好顯示。false表示交給Glide

如此修改後,就可以看到圖片加載日誌了,方便咱們調試

替換掉自帶的HttpClient

只需兩步
Step1:
導入須要替換的HttpClient,能夠選擇Volley也能夠選擇OkHttp,咱們使用Okhttp,在Module的build.gradle文件中配置

  1.  
    dependencies {
  2.  
    compile 'com.github.bumptech.glide:okhttp3-integration:1.4.0@aar'
  3.  
    compile 'com.squareup.okhttp3:okhttp:3.3.1'
  4.  
     
  5.  
    or
  6.  
     
  7.  
    compile 'com.github.bumptech.glide:volley-integration:1.4.0@aar'
  8.  
    compile 'com.mcxiaoke.volley:library:1.0.8'
  9.  
    }

這個版本具體選擇多少,能夠在https://github.com/bumptech/glide/wiki/Integration-Libraries這裏查詢到
Step2:
在AndroidMainfest.xml文件中寫入

這個版本具體選擇多少,能夠在https://github.com/bumptech/glide/wiki/Integration-Libraries這裏查詢到
Step2:
在AndroidMainfest.xml文件中寫入

  1.  
    <meta-data android:name= "com.bumptech.glide.integration.okhttp3.OkHttpGlideModule"
  2.  
    android: value="GlideModule"/>

你可能會有和我同樣的疑問,Glide能夠經過在配置清單裏面配置
能不能寫幾個meta-data標籤,一個標籤裏面配置一點參數
通過測試,發現這樣作也是能夠的。可是若是是同一種配置信息,好比你集成了OkHttp,又寫一個標籤集成Volley,最後一個會把前面的覆蓋掉。

注意事項

一、前面咱們已經學習到asGif()能夠加載gif圖,asBitmap()能夠加載靜態gif圖即gif圖的第一幀,若是非gif圖用asGif()方法加載呢?這時候會報錯。。Glide默承認以自動識別圖片格式,加載gif圖,因此在不肯定圖片格式的狀況下,不要直接寫asGif哦。

二、You cannot start a load for a destroyed activity這樣的異常如何處理?
記住不要再非主線程裏面使用Glide加載圖片,若是真的使用了,請把context參數換成getApplicationContext。但願能夠幫你避免這個問題。

三、爲何有的圖片第一次加載的時候只顯示佔位圖,第二次才顯示正常的圖片呢?
.若是你恰好使用了這個圓形Imageview庫或者其餘的一些自定義的圓形Imageview,而你又恰好設置了佔位的話,那麼,你就會遇到第一個問題。如何解決呢?

方案一: 不設置佔位;
方案二:使用Glide的Transformation API自定義圓形Bitmap的轉換。這裏是一個已有的例子;
方案三:使用下面的代碼加載圖片:

  1.  
    Glide.with(mContext)
  2.  
    .load(url)
  3.  
    .placeholder(R.drawable.loading_spinner)
  4.  
    .into( new SimpleTarget<Bitmap>(width, height) {
  5.  
    @Override
  6.  
    public void onResourceReady(Bitmap bitmap, GlideAnimation anim) {
  7.  
    // setImageBitmap(bitmap) on CircleImageView
  8.  
    }
  9.  
    };

四、圖片大小拉伸問題
有時候你會發現網絡加載完了以後會有拉伸現象,而你的控件大小明明是自適應的呀,這是爲何呢,請你檢查下你是否設置了佔位圖,有的話請去掉就ok了。

 

簡單總結一下,我這裏講了Glide比較全面的用法,有如何加載圖片,Glide的緩衝設置,Glide設置圓角,Glide設置圖片的background,Glide加載GIF圖片等,你們使用的話通常瞭解加載圖片和圓角圖片就能夠了。這裏在列舉一下。

  1.  
    //圓形裁剪
  2.  
    Glide.with( this)
  3.  
    .load( "http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png")
  4.  
    .bitmapTransform( new CropCircleTransformation(this))
  5.  
    . into(iv_0);
  6.  
    //圓角處理
  7.  
    Glide.with( this)
  8.  
    .load( "http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png")
  9.  
    .bitmapTransform( new RoundedCornersTransformation(this,30,0, RoundedCornersTransformation.CornerType.ALL))
  10.  
    . into(iv_0);

android Glide簡單使用就講完了。

就這麼簡單。

相關文章
相關標籤/搜索