本文是研讨官方core-ktx库的第五篇同样也是最终一篇文章,旨在探究该库中有哪些工具类或办法能够提高咱们的开发功率。

已更新的系列文章:

你需要了解的官方core-ktx库能对开发带来哪些便当?

官方core-ktx库能对富文本Span开发带来哪些便当?

官方core-ktx库能对SparseArray系列、Pair开发带来哪些便当?

超好用的官方core-ktx库,了解一下~

Handler.postDelayed()简化lambda传入

不知道咱们在运用Handler下的postDelayed()办法是不是感觉很不简练,咱们看下这个函数源码:

public final boolean postDelayed(@NonNull Runnable r, long delayMillis) {
    return sendMessageDelayed(getPostMessage(r), delayMillis);
}

能够看到Runnable类型的参数r放在第一位,在Kotlin中咱们就无法运用其供给的简练的语法糖,只能这样运用:

private fun test11(handler: Handler) {
    handler.postDelayed({
        //编写代码逻辑
    }, 100)
}

有没有感觉很别扭,估量官方也发现了这个问题,就供给了这样一个扩展办法:

public inline fun Handler.postDelayed(
    delayInMillis: Long,
    token: Any? = null,
    crossinline action: () -> Unit
): Runnable {
    val runnable = Runnable { action() }
    if (token == null) {
        postDelayed(runnable, delayInMillis)
    } else {
        HandlerCompat.postDelayed(this, runnable, token, delayInMillis)
    }
    return runnable
}

能够看到将函数类型(相当于上面的Runnable中的代码履行逻辑)放到了办法参数的最终一位,这样运用kotlin的语法糖就能够这样运用:

private fun test11(handler: Handler) {
    handler.postDelayed(200) {
    }
}

能够看到这个函数类型运用了crossinline修饰,这个是用来加强内联的,因为其另一个Runnable的函数类型中进行了调用,这样咱们就无法在这个函数类型action中运用return关键字了(return@标签在外),防止运用return关键字带来回来上的歧义不稳定性

除此之外,官方core-ktx还供给了相似的扩展办法postAtTime()办法,运用和上面相同!!

Context.getSystemService()泛型实化获取系统服务

看下以往咱们怎么获取ClipboardManager:

private fun test11() {
    val cm: ClipboardManager = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
}

看下官方供给的办法:

public inline fun <reified T : Any> Context.getSystemService(): T? =
    ContextCompat.getSystemService(this, T::class.java)

凭借于内联泛型实化简化了获取系统服务的代码逻辑:

private fun test11() {
    val cm: ClipboardManager? = getSystemService()
}

泛型实化的用途有很多运用场景,咱们感兴趣能够参考我另一篇文章:Gson序列化的TypeToken写起来太麻烦?优化它

Context.withStyledAttributes简化操作自定义特点

这个扩展一般只有在自定义View中较常运用,比方读取xml中设置的特点值,先看下咱们平常是如何运用的:

private fun test11(
    @NonNull context: Context,
    @Nullable attrs: AttributeSet,
    defStyleAttr: Int
) {
    val ta = context.obtainStyledAttributes(
        attrs, androidx.cardview.R.styleable.CardView, defStyleAttr,
        androidx.cardview.R.style.CardView
    )
    //获取特点履行对应的操作逻辑
    val tmp = ta.getColorStateList(androidx.cardview.R.styleable.CardView_cardBackgroundColor)
    ta.recycle()
}

在获取完特点值后,还需要调用recycle()办法收回TypeArray,这个一旦忘记写就不好了,能让程序确保的写法那就尽量防止人为处理,所以官方供给了下面的扩展办法:

public inline fun Context.withStyledAttributes(
    @StyleRes resourceId: Int,
    attrs: IntArray,
    block: TypedArray.() -> Unit
) {
    obtainStyledAttributes(resourceId, attrs).apply(block).recycle()
}

运用如下:

private fun test11(
    @NonNull context: Context,
    @Nullable attrs: AttributeSet,
    defStyleAttr: Int
) {
    context.withStyledAttributes(
        attrs, androidx.cardview.R.styleable.CardView, defStyleAttr,
        androidx.cardview.R.style.CardView
    ) {
        val tmp = getColorStateList(androidx.cardview.R.styleable.CardView_cardBackgroundColor)
    }
}

上面的写法就确保了recycle()不会漏写,而且带接收者的函数类型block: TypedArray.() -> Unit也能让咱们省掉this直接调用TypeArray中的公共办法。

SQLiteDatabase.transaction()主动敞开业务读写数据库

平常对SQLite进行写操作时为了功率及安全确保需要敞开业务,一般咱们都会手动进行敞开和封闭,仍是那句老话,能程序主动确保的工作就尽量防止手动完结,所以一般咱们都会封装一个业务敞开和封闭的办法,如下:

private fun writeSQL(sql: String) {
    SQLiteDatabase.beginTransaction()
    //履行sql写入语句
    SQLiteDatabase.endTransaction()
}

官方core-ktx也供给了相似的扩展办法:

public inline fun <T> SQLiteDatabase.transaction(
    exclusive: Boolean = true,
    body: SQLiteDatabase.() -> T
): T {
    if (exclusive) {
        beginTransaction()
    } else {
        beginTransactionNonExclusive()
    }
    try {
        val result = body()
        setTransactionSuccessful()
        return result
    } finally {
        endTransaction()
    }
}

咱们能够自行挑选运用!

<K : Any, V : Any> lruCache()简化创立LruCache

LruCache一般用作数据缓存,里面运用了LRU算法来优先淘汰那些近期最少运用的数据。在Android开发中,咱们能够运用其规划一个Bitmap缓存池,感兴趣的能够参考Glide内存缓存这块的源码,就运用了LruCache完结。

相比较于原有创立LruCache的办法,官方库供给了下面的扩展办法简化其创立流程:

inline fun <K : Any, V : Any> lruCache(
    maxSize: Int,
    crossinline sizeOf: (key: K, value: V) -> Int = { _, _ -> 1 },
    @Suppress("USELESS_CAST")
    crossinline create: (key: K) -> V? = { null as V? },
    crossinline onEntryRemoved: (evicted: Boolean, key: K, oldValue: V, newValue: V?) -> Unit =
        { _, _, _, _ -> }
): LruCache<K, V> {
    return object : LruCache<K, V>(maxSize) {
        override fun sizeOf(key: K, value: V) = sizeOf(key, value)
        override fun create(key: K) = create(key)
        override fun entryRemoved(evicted: Boolean, key: K, oldValue: V, newValue: V?) {
            onEntryRemoved(evicted, key, oldValue, newValue)
        }
    }
}

看下运用:

private fun createLRU() {
    lruCache<String, Bitmap>(3072, sizeOf = { _, value ->
        value.byteCount
    }, onEntryRemoved = { evicted: Boolean, key: String, oldValue: Bitmap, newValue: Bitmap? ->
        //缓存目标被移除的回调办法
    })
}

能够看到,比之手动创立LruCache要稍微简单些,能稍微节约下运用本钱。

bundleOf()方便写入并创立Bundle目标

超好用的官方core-ktx库,了解一下(终)~

bundleOf()办法的参数被vararg声明,代表一个可变的参数类型,参数具体的类型为Pair,这个目标咱们之前的文章有讲过,能够凭借中缀表达式函数to完结Pair的创立:

private fun test12() {
    val bundle = bundleOf("a" to "a", "b" to 10)
}

这种通过传入可变参数完结的Bundle假如咱们不太喜欢,还能够考虑自行封装通用扩展函数,在函数类型即lambda中完结愈加灵敏的Bundle创立及写入:

1.自定义运算符重载办法set完结Bundle写入:

operator fun Bundle.set(key: String, value: Any?) {
    when (value) {
        null -> putString(key, null)
        is Boolean -> putBoolean(key, value)
        is Byte -> putByte(key, value)
        is Char -> putChar(key, value)
        is Double -> putDouble(key, value)
        is Float -> putFloat(key, value)
        is Int -> putInt(key, value)
        is Long -> putLong(key, value)
        is Short -> putShort(key, value)
        is Serializable -> putSerializable(key, value)
        //其实数据类型自定参考bundleOf源码完结
    }
}

2.自定义BundleBuild支持向Bundle写入多个值

class BundleBuild(private val bundle: Bundle) {
    infix fun String.to(that: Any?) {
        bundle[this] = that
    }
}

其间to()办法运用了中缀表达式的写法

3.暴漏扩展办法完结在lambda中完结Bundle的写入和创立

private fun bundleOf(block: BundleBuild.() -> Unit): Bundle {
    return Bundle().apply {
        BundleBuild(this).apply(block)
    }
}

然后就能够这样运用:

private fun test12() {
    val bundle = bundleOf {
        "a" to "haha"
        //经过一些逻辑操作获取成果后在写入Bundle
        val t1 = 10 * 5
        val t2 = ""
        t2 to t1
    }
}

相比较于官方库供给的bundleOf()供给的创立办法,通过函数类型也就是lambda创立并写入Bundle的办法愈加灵敏,并内部支持履行操作逻辑获取成果后再进行写入。

总结

关于官方core-ktx的研讨基本上已经七七八八了,一共输出了五篇相关文章,对该库了解能够节约咱们编写模板代码的时间,提高开发功率,咱们假如感觉写的不错,能够点个赞支持下哈,感谢!!

我正在参加技能社区创作者签约方案招募活动,点击链接报名投稿。