本文是研讨官方
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目标
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
的研讨基本上已经七七八八了,一共输出了五篇相关文章,对该库了解能够节约咱们编写模板代码的时间,提高开发功率,咱们假如感觉写的不错,能够点个赞支持下哈,感谢!!
我正在参加技能社区创作者签约方案招募活动,点击链接报名投稿。