亚洲欧美日韩熟女|做爱高潮视频网址|国产一区二区三级片|国产Av中文字幕www.性色av|亚洲婷婷永久免费|国产高清中文字幕|欧美变态网站久re视频精品|人妻AV鲁丝第一页|天堂AV一区二区在线观看|综合 91在线精品

Android 圖片加載庫之Coil的詳解與使用

2023-04-12


一、介紹


在Android,資源的呈現(xiàn)主要有三大形式:文字、圖片、視頻。圖片有分為本地資源和網(wǎng)絡(luò)資源。


網(wǎng)絡(luò)資源需要通過下載然后綁定到ImageView中。


在前期我們使用的圖片加載框架如:picasso、gliade、imageload。這些框架都可以滿足我們正常的圖片加載到顯示,且這些框架都是通過Java語言開發(fā)出來。接下來,我將介紹一款以kotlin語言開發(fā)的框架Coil。


Coil的介紹


一、介紹


是一個(gè) Android 圖片加載庫,通過Kotlin協(xié)程的方式加載圖片


優(yōu)勢

  • 更快:

    Coil 在性能上有很多優(yōu)化,包括內(nèi)存緩存和磁盤緩存,把縮略圖存保存在內(nèi)存中,循環(huán)利用 bitmap,自動暫停和取消圖片網(wǎng)絡(luò)請求等。
  • 更輕量級:

    Coil 的包體很小,很多API依賴項(xiàng)目中的其他模塊的框架(如:前提是你的 APP 里面集成了 OkHttp 和 Coroutines),Coil 和 Picasso 的方法數(shù)差不多,相比 Glide 和 Fresco 要輕量很多,kotlin的語法支持,代碼更簡潔。
  • 更容易使用:

    Coil 的 API 充分利用了 Kotlin 語言的新特性,簡化和減少了很多樣板代碼,采用了類方法擴(kuò)展,常用的API已通過ImageViews擴(kuò)展到了ImageView中,可以直接使用
  • 更流行更新:

    Coil 首選 Kotlin 語言開發(fā)并且使用包含 Coroutines, OkHttp, Okio 和 AndroidX Lifecycles 在內(nèi)最流行的開源庫,很好的兼容最新Jetpack組件。

2、集成

io.coil-kt:coil-base : 基礎(chǔ)組件,提供了基本的圖片請求、圖片解碼、圖片緩存等
io.coil-kt:coil : 默認(rèn)組件,依賴于io.coil-kt:coil-base,提供了 Coil 類的單例對象以及 ImageViews 相關(guān)的擴(kuò)展函數(shù)
io.coil-kt:coil-gif : 用于支持解碼 GIFs
io.coil-kt:coil-svg : 用于支持解碼 SVG
io.coil-kt:coil-video : 包含兩個(gè) fetchers 用于支持讀取和解碼 任何 Android 的支持的視頻格式 的視頻幀


//依賴庫

implementation("io.coil-kt:coil:1.2.2")
//    //選擇添加
    implementation("io.coil-kt:coil-gif:1.2.2")//支持GIF
    implementation("io.coil-kt:coil-svg:1.2.2")//支持SVG
    implementation("io.coil-kt:coil-video:1.2.2")//支持Video

3、使用

由于在kotlin支持方法的擴(kuò)展,所以ImageViews已支持提供了load方法,默認(rèn)只需要傳入圖片地址即可。


@JvmSynthetic
inline fun ImageView.load(
    uri: String?,
    imageLoader: ImageLoader = context.imageLoader,
    builder: ImageRequest.Builder.() -> Unit = {}
): Disposable = loadAny(uri, imageLoader, builder)

/** @see ImageView.loadAny */
@JvmSynthetic
inline fun ImageView.load(
    url: HttpUrl?,
    imageLoader: ImageLoader = context.imageLoader,
    builder: ImageRequest.Builder.() -> Unit = {}
): Disposable = loadAny(url, imageLoader, builder)

/** @see ImageView.loadAny */
@JvmSynthetic
inline fun ImageView.load(
    uri: Uri?,
    imageLoader: ImageLoader = context.imageLoader,
    builder: ImageRequest.Builder.() -> Unit = {}
): Disposable = loadAny(uri, imageLoader, builder)

/** @see ImageView.loadAny */
@JvmSynthetic
inline fun ImageView.load(
    file: File?,
    imageLoader: ImageLoader = context.imageLoader,
    builder: ImageRequest.Builder.() -> Unit = {}
): Disposable = loadAny(file, imageLoader, builder)

/** @see ImageView.loadAny */
@JvmSynthetic
inline fun ImageView.load(
    @DrawableRes drawableResId: Int,
    imageLoader: ImageLoader = context.imageLoader,
    builder: ImageRequest.Builder.() -> Unit = {}
): Disposable = loadAny(drawableResId, imageLoader, builder)

/** @see ImageView.loadAny */
@JvmSynthetic
inline fun ImageView.load(
    drawable: Drawable?,
    imageLoader: ImageLoader = context.imageLoader,
    builder: ImageRequest.Builder.() -> Unit = {}
): Disposable = loadAny(drawable, imageLoader, builder)

/** @see ImageView.loadAny */
@JvmSynthetic
inline fun ImageView.load(
    bitmap: Bitmap?,
    imageLoader: ImageLoader = context.imageLoader,
    builder: ImageRequest.Builder.() -> Unit = {}
): Disposable = loadAny(bitmap, imageLoader, builder)

load支持的請求類型

uri: String:圖片地址



url: HttpUrl:封裝好的請求url



uri: Uri:Uri的資源封裝



file: File:文件類型



drawableResId: Int:資源id



drawable: Drawable:drawable對象



bitmap: Bitmap:bitmap對象




加載load,返回一個(gè)Disposable,Disposable是IPC的接口,如下

interface Disposable {

    /**
     * Returns true if the request is complete or cancelling.
     */
    val isDisposed: Boolean

    /**
     * Cancels any in progress work and frees any resources associated with this request. This method is idempotent.
     */
    fun dispose()

    /**
     * Suspends until any in progress work completes.
     */
    @ExperimentalCoilApi
    suspend fun await()
}

通過Disposable可以判斷是否完成,主動調(diào)用以及等待。


擴(kuò)展:

Coil不僅提供了默認(rèn)的加載,還可以擴(kuò)展其他。


inline fun ImageView.load(
    uri: String?,
    imageLoader: ImageLoader = context.imageLoader,
    builder: ImageRequest.Builder.() -> Unit = {}
): Disposable = loadAny(uri, imageLoader, builder)

通過源碼可以看到,requestbuild是支持?jǐn)U展的。默認(rèn)后面是{},可以在{}體中調(diào)用build中方法。


bind.image.load(url){
                //build 擴(kuò)展體
                crossfade(true) //漸進(jìn)漸出
                placeholder(R.mipmap.ic_launcher) //加載中占位圖
                error(R.mipmap.ic_launcher)  //加載失敗占位圖
                allowHardware(true)//硬件加速
                allowRgb565(true)//支持565格式

                lifecycle(lifecycle)//生命周期關(guān)聯(lián)
                var default= DefaultRequestOptions()
                defaults(default)
            }

包括網(wǎng)絡(luò)緩存等,我們可以自己根據(jù)業(yè)務(wù)配置。如果你需要可以自定義一個(gè)ImageRequest.Build


ImageView高階變換


Transformation(圖片變換)

  • BlurTransformation() : 高斯模糊變換
  • CircleCropTransformation() : 圓形裁剪變換
  • GrayscaleTransformation() : 灰度變換
  • RoundedCornersTransformation() : 圓角變換





高階圖片變形通過transformations()來完成,支持多樣式。





BlurTransformation() : 高斯模糊變換

class BlurTransformation @JvmOverloads constructor(
    private val context: Context,
    private val radius: Float = DEFAULT_RADIUS,
    private val sampling: Float = DEFAULT_SAMPLING
)
init {
        require(radius in 0.0..25.0) { "radius must be in [0, 25]." }
        require(sampling > 0) { "sampling must be > 0." }
    }

1.radius:模糊半徑范圍在0到25之間,數(shù)值越大,模糊越深


2.sampling:采樣率必須大于,這個(gè)值是進(jìn)行縮放圖片大小的,(0,1),圖片是越來越大,[1,++oo),圖片是越來越小



GrayscaleTransformation() : 灰度變換

這個(gè)主要把彩色的圖片置灰,常見特殊忌日,可以設(shè)置,利用了ColorMatrixColorFilter對顏色進(jìn)行過濾。


RoundedCornersTransformation:圓角角度設(shè)置



class RoundedCornersTransformation( @Px private val topLeft: Float = 0f, @Px private val topRight: Float = 0f, @Px private val bottomLeft: Float = 0f, @Px private val bottomRight: Float = 0f )





A=topleft ,B=topright,C=bottomLeft,D=bottomRight。


如果只傳一個(gè)參數(shù),默認(rèn)就是四個(gè)角的角度,角度默認(rèn)值是0,任何角的坐標(biāo)都是(x,y),所以你設(shè)置角度無法只設(shè)置一個(gè)叫的一半。


如果想了解view的角度自定義,可以查看:


Android ImageView 四個(gè)角自定義角度,以及角度的變換_addroundrect_蝸牛、Z的博客-CSDN博客


參數(shù)擴(kuò)展

有人用習(xí)慣了Glide或者imageload,會發(fā)現(xiàn),可以通過配置來管理加載中,加載失敗等標(biāo)識,Coil同樣也支持,只是通過build提供的方法來完成。


inline fun ImageView.load(
    uri: String?,
    imageLoader: ImageLoader = context.imageLoader,
    builder: ImageRequest.Builder.() -> Unit = {}
): Disposable = loadAny(uri, imageLoader, builder)
bind.load.setOnClickListener {
            bind.image.load("https://img-blog.csdnimg.cn/3a4114c916904ecbadb7a71b77294eef.gif"){
                crossfade(true) //漸進(jìn)漸出
                placeholder(R.mipmap.ic_launcher) //加載中占位圖
                error(R.mipmap.ic_launcher)  //加載失敗占位圖
                allowHardware(true)//硬件加速
//                transformations(BlurTransformation(context,25f,2f))
                //圓角
                transformations(RoundedCornersTransformation(90f,0f,0f,0f))
            }
        }

有人會有疑問:

builder: ImageRequest.Builder.() -> Unit = {}


這個(gè)寫法,是返回builder類,通過指向類的內(nèi)部方法來完成,最后返回build。


小試牛刀:

class Build {

      var msgs: String? = ""

    fun setMsg(msg: String) = apply {
        this.msgs = msg
    }
}


class TestBody(var build: Build.() -> Unit = {}) {

    fun log() {

        var mBuild = Build()
        mBuild.apply(build)
        mBuild.msgs?.let { MyLog.log(it) }
    }
}


fun main() {
    var test = TestBody({
        setMsg("hello")
    })

    test.log()
}

build是一個(gè)block object的,我們可以通過Build對象apply方法copy這個(gè)對象。


GIF動態(tài)圖片加載


Coil庫不僅支持靜態(tài)圖片,也支持動態(tài)圖片。只是動態(tài)和靜態(tài)的解析對象不同ComponentRegistry在注冊的時(shí)候,已提供了各種攔截與支持。


依賴庫的引入:



implementation("io.coil-kt:coil-gif:1.2.2")//支持GIF





decoder目前提供兩種方式:

api<28

/**
 * A [Decoder] that uses [Movie] to decode GIFs.
 *
 * NOTE: Prefer using [ImageDecoderDecoder] on API 28 and above.
 */
class GifDecoder : Decoder

api>=28

/**
 * A [Decoder] that uses [ImageDecoder] to decode GIFs, animated WebPs, and animated HEIFs.
 *
 * NOTE: Animated HEIF files are only supported on API 30 and above.
 */
@RequiresApi(28)
class ImageDecoderDecoder : Decoder

ImageLoad初始化:

注意GIFDecoder類的頂部注釋:


NOTE: Prefer using ImageDecoderDecoder on API 28 and above.


//創(chuàng)建 gif ImageLoader 實(shí)例
        val imageLoader = ImageLoader.Builder(applicationContext)
            .componentRegistry {
                if (SDK_INT >= 28) {
                    add(ImageDecoderDecoder(applicationContext))
                } else {
                    add(GifDecoder())
                }
            }.build()
        //設(shè)置全局唯一實(shí)例
        Coil.setImageLoader(imageLoader)

這樣我們就完成了Gif的ImageLoader的設(shè)置


如何監(jiān)聽圖片加載:




ImageRequest提供了fun listener(listener: Listener?) 方法。




bind.image.load("https://img-blog.csdnimg.cn/3a4114c916904ecbadb7a71b77294eef.gif") {
  
                listener(object : ImageRequest.Listener {
                    override fun onCancel(request: ImageRequest) {
                        super.onCancel(request)
                    }

                    override fun onSuccess(request: ImageRequest, metadata: ImageResult.Metadata) {
                        super.onSuccess(request, metadata)
                    }

                    override fun onError(request: ImageRequest, throwable: Throwable) {
                        super.onError(request, throwable)
                    }

                    override fun onStart(request: ImageRequest) {
                        super.onStart(request)
                    }
                })
            }

關(guān)于配置

上面都是通過方法設(shè)置配置參數(shù),如何設(shè)置全局配置?需要我們自己去設(shè)置一個(gè)全局的ImageLoader.Builder


val okHttpClient = OkHttpClient.Builder()
            .cache(CoilUtils.createDefaultCache(this))
            .build()

        val imageLoader = ImageLoader.Builder(this)
            .availableMemoryPercentage(0.5f)
            .diskCachePolicy(CachePolicy.ENABLED)  //磁盤緩策略 ENABLED、READ_ONLY、WRITE_ONLY、DISABLED
            .crossfade(true) //淡入淡出
            .okHttpClient {  //設(shè)置okhttpClient實(shí)例
                okHttpClient
            }.build()

        Coil.setImageLoader(imageLoader)

api介紹:

1.availableMemoryPercentage:

設(shè)置用于此 ImageLoader 的內(nèi)存緩存和位圖池的可用內(nèi)存百分比,如果設(shè)置了百分百,那么cache將會失效


//源碼
   fun availableMemoryPercentage(@FloatRange(from = 0.0, to = 1.0) percent: Double) = apply {
            require(percent in 0.0..1.0) { "Percent must be in the range [0.0, 1.0]." }
            this.availableMemoryPercentage = percent
            this.memoryCache = null
        }

2.memoryCachePolicy :

內(nèi)存緩存策略,有4中策略;


3.diskCachePolicy:

磁盤緩存策略,方式和內(nèi)存策略一致;


CachePolicy.ENABLED : 可讀可寫
CachePolicy.READ_ONLY : 只讀
CachePolicy.WRITE_ONLY : 只寫
CachePolicy.DISABLED : 不可讀不可寫,即禁用


短視頻首幀


Coil還有特別特別項(xiàng),支持短視頻首幀圖片加載。正常在項(xiàng)目中,如果該項(xiàng)目有短視頻業(yè)務(wù),在視頻不播放的狀態(tài)下,如何獲取首幀圖片?這個(gè)問題是很多公司思考的問題。


大公司在處理視頻首幀都是通過服務(wù)器跑的。這樣,在視頻集在列表展示只處理單張圖片即可。針對某一個(gè)視頻,特別是小公司的時(shí)候,Coil明顯很友好,可以在接收的范圍類,降低技術(shù)和服務(wù)器的成本。


依賴庫的引入:



implementation("io.coil-kt:coil-video:1.2.2")//支持Video




添加VideoDecoder


//創(chuàng)建 gif ImageLoader 實(shí)例
        val imageLoader = ImageLoader.Builder(applicationContext)
            .componentRegistry {
               add(VideoFrameDecoder(context))
            }.build()

        //設(shè)置全局唯一實(shí)例
        Coil.setImageLoader(imageLoader)

剩余的設(shè)置,都是通用設(shè)置,如果項(xiàng)目需要支持GIF、VideoFrame,可以同時(shí)支持進(jìn)去,都是通過componentRegistry add添加,可以追加進(jìn)去。



本文僅代表作者觀點(diǎn),版權(quán)歸原創(chuàng)者所有,如需轉(zhuǎn)載請?jiān)谖闹凶⒚鱽碓醇白髡呙帧?/p>

免責(zé)聲明:本文系轉(zhuǎn)載編輯文章,僅作分享之用。如分享內(nèi)容、圖片侵犯到您的版權(quán)或非授權(quán)發(fā)布,請及時(shí)與我們聯(lián)系進(jìn)行審核處理或刪除,您可以發(fā)送材料至郵箱:service@tojoy.com