You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Android的TypedArray存在自定义use扩展函数实现?

TypedArray自定义use扩展函数的存在原因解析

背景

Android中的TypedArray使用完毕后必须调用recycle()方法回收资源,避免内存泄漏。它实现了AutoCloseable接口,因此理论上可以直接使用Kotlin标准库的.use { ... }函数自动完成回收操作。

Kotlin标准库的use函数实现如下:

@Suppress("ACTUAL_WITHOUT_EXPECT")
@SinceKotlin("1.2")
@kotlin.internal.InlineOnly
// TODO: remove java.lang package prefix when the kotlin.AutoCloseable typealias is introduced and KT-55392 is fixed.
//   The prefix is currently needed for the current dokka to generate correct signature.
public actual inline fun <T : java.lang.AutoCloseable?, R> T.use(block: (T) -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    var exception: Throwable? = null
    try {
        return block(this)
    } catch (e: Throwable) {
        exception = e
        throw e
    } finally {
        this.closeFinally(exception)
    }
}

@SinceKotlin("1.2")
@PublishedApi
internal fun java.lang.AutoCloseable?.closeFinally(cause: Throwable?) = when {
    this == null -> {}
    cause == null -> close()
    else -> 
        try {
            close()
        } catch (closeException: Throwable) {
            cause.addSuppressed(closeException)
        }
}

TypedArray对close()方法的重写逻辑非常简单,直接调用recycle():

public void close() {
  recycle();
}

但Android SDK还单独为TypedArray提供了一个同名的自定义use扩展函数:

public inline fun <R> TypedArray.use(block: (TypedArray) -> R): R {
    return block(this).also {
        recycle()
    }
}

自定义use扩展函数的存在原因

1. 历史兼容性

TypedArray是从Android API 24开始才实现AutoCloseable接口的。在这之前,低版本的Android项目无法使用Kotlin标准库的use函数来自动回收TypedArray。这个自定义扩展函数的出现,是为了让API 24以下的项目也能通过简洁的use语法安全管理TypedArray资源。

2. 简化逻辑与微小性能优化

标准库的use函数是通用实现,需要适配所有AutoCloseable类型:

  • 它会处理block执行时抛出异常的情况,若close()也抛出异常,会将其标记为被抑制的异常;
  • 支持可空的AutoCloseable?类型,因此包含空值判断逻辑。

而TypedArray的recycle()方法不会抛出任何异常(官方文档明确说明),自定义的use函数可以完全省去这些通用化的异常处理和空值检查逻辑,直接在block执行完成后调用recycle()。虽然单看一次调用性能提升不明显,但在频繁创建TypedArray的场景(比如列表Adapter的getView方法中),累计下来的开销节省是可感知的。

同时,自定义实现的代码逻辑更直观简洁,直接通过also函数完成回收操作。

3. 语义更贴合场景

标准库的use函数是针对所有资源的通用关闭逻辑,而自定义的TypedArray.use函数直接绑定recycle()操作,语义上更贴合TypedArray的资源回收场景,让代码意图更清晰。

关于同名函数的导入问题

你提到的同名函数容易导错的问题确实存在,当项目同时引入Kotlin标准库和Android SDK相关依赖时,IDE会提示多个use函数可选。可以通过以下方式规避:

  • 明确指定导入路径:在代码顶部添加import android.content.res.TypedArray.use,强制使用Android自定义版本;
  • 若项目仅支持API 24及以上,可直接使用标准库的use函数,无需导入Android的扩展版本。

内容的提问来源于stack exchange,提问作者NoBullsh1t

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 21:05:07