当前位置: 代码网 > it编程>App开发>Android > Android Kotlin开发中常用函数使用手册

Android Kotlin开发中常用函数使用手册

2026年09月22日 • Android •我要评论
涵盖:作用域函数(let / run / with / apply / also)、委托(by)、惰性初始化(lazy)、 以及 takeif、runcatching、use 等高频工具函数。1.le

涵盖:作用域函数(let / run / with / apply / also)、委托(by)、惰性初始化(lazy)、 以及 takeif、runcatching、use 等高频工具函数。

1.let

签名:inline fun <t, r> t.let(block: (t) -> r): r

对非空对象执行操作,并可改变返回类型。

1.1 空安全调用(最常用)

val name: string? = user?.nickname
​
// 传统写法
if (name != null) {
    log.d(tag, "长度 = ${name.length}")
}
​
// let 写法:只在非空时执行
name?.let {
    log.d(tag, "长度 = ${it.length}")
}
​
// 结合 elvis:为空时给兜底
val display = name?.let { "昵称:$it" } ?: "昵称:未设置"

1.2 给表达式起局部名字

// 避免写两次耗时函数
getusername()?.let { n ->
    println("你好,$n")
    cache.put("name", n)
}

1.3 链式转换(把 a 类型转成 b 类型)

val length: int? = listof("a", "bb", "ccc")
    .firstornull { it.length > 1 }
    .let { it?.length ?: 0 }

1.4 限制变量作用域

val result = calculatetotal().let { total ->
    // total 只在这个块内可见,避免污染外部作用域
    if (total > 1000) total * 0.9 else total
}

1.5 android:点击事件里避免重复 find

binding.btnsubmit.setonclicklistener {
    viewmodel.submit()?.let { state ->
        toast.maketext(this, state.message, toast.length_short).show()
    }
}

2.run

签名

inline fun <r> run(block: () -> r): r            // 非扩展:开一个新作用域
inline fun <t, r> t.run(block: t.() -> r): r     // 扩展:接收者是 this

2.1t.run {}—— 判空 + 一串操作

val user: user? = repository.finduser(id)
​
val summary = user?.run {
    // 这里 this 就是 user,属性可省略 this.
    "$name($age 岁)"
} ?: "用户不存在"

2.2 非扩展run {}—— 需要一段"临时作用域"

val padding = run {
    val base = resources.getdimensionpixelsize(r.dimen.base)
    val half = base / 2
    half * 3            // 最后一行就是 run 的返回值
}

2.3 android:一段有中间变量的计算

private fun buildquery(): map<string, string> = run {
    val page = currentpage + 1
    val size = pagesize.coerceatmost(50)
    mapof("page" to "$page", "size" to "$size")
}

2.4 android:把一串 ui 操作收拢

fun showemptystate() {
    binding.emptyview.run {
        isvisible = true
        text = getstring(r.string.empty_tip)
        setonclicklistener { viewmodel.reload() }
    }
}

3.with

签名:inline fun <t, r> with(receiver: t, block: t.() -> r): r

注意:with 不是扩展函数,它是普通函数,接收者作为第一个参数传入。

3.1 对同一对象做多次操作

val sb = stringbuilder()
with(sb) {
    append("hello")
    append(", ")
    append("kotlin")
}
println(sb.tostring())  // hello, kotlin

3.2 android:一次性配置 recyclerview

with(binding.recyclerview) {
    layoutmanager = linearlayoutmanager(context)
    adapter = orderadapter
    sethasfixedsize(true)
    additemdecoration(divideritemdecoration(context, divideritemdecoration.vertical))
}

3.3 android:解析 bundle / 读取 intent 参数

val detail = with(requirearguments()) {
    detailargs(
        id = getstring("id") ?: "",
        from = getstring("from") ?: "unknown",
        editable = getboolean("editable", false)
    )
}

3.4 什么时候用with而不是t.run?

// 两者等价,写法差异:
with(user) { println(name) }   // with(user) { ... }
user.run { println(name) }     // user.run { ... }

// 习惯:可空对象用 ?.run {},非空对象用 with(x) {} 更直观

4.apply

签名:inline fun <t> t.apply(block: t.() -> unit): t

返回对象本身,块内 this 是对象,适合"创建即配置"。

4.1 创建时批量设置属性

val intent = intent(context, detailactivity::class.java).apply {
    putextra("id", orderid)
    putextra("from", "list")
    flags = intent.flag_activity_new_task
}
startactivity(intent)

4.2 android:构建 dialog / 配置 view

alertdialog.builder(this).apply {
    settitle(r.string.tip)
    setmessage(r.string.confirm_delete)
    setpositivebutton(r.string.ok) { _, _ -> viewmodel.delete() }
    setnegativebutton(r.string.cancel, null)
}.show()

4.3 初始化一个数据对象

val request = orderrequest().apply {
    userid = uid
    page = 1
    pagesize = 20
    sort = "createtime,desc"
}

4.4 链式:apply之后继续用对象

val text = textview(context).apply {
    this.text = "标题"          // 与属性名冲突时用 this 区分
    textsize = 16f
    settextcolor(color.black)
    gravity = gravity.center
}.text.tostring()

apply 里如果省略 this.,要注意「参数名/属性名同名」的遮蔽问题。

5.also

签名:inline fun <t> t.also(block: (t) -> unit): t

返回对象本身,块内用 it,非常适合插入副作用而不打断链式调用。

5.1 打日志 / 埋点

val order = repository.createorder(req)
    .also { log.d(tag, "创建订单成功: ${it.id}") }
    .also { analytics.track("order_created", mapof("id" to it.id)) }

5.2 链式中的校验

val file = file(path)
    .also { require(it.exists()) { "文件不存在: $path" } }
    .also { require(it.canread()) { "文件不可读" } }

5.3 区分apply和also

// apply:配置对象内部,省略 this
val user = user().apply {
    name = "tom"        // 等价 this.name = "tom"
}

// also:对外部变量做副作用,必须用 it
val user = user().also {
    it.name = "tom"     // 必须写 it.name
    loguser(it)         // 副作用:记录日志
}

6.lazy惰性初始化

签名:fun <t> lazy(initializer: () -> t): lazy<t>

第一次访问才初始化,之后复用缓存值。

6.1 基础用法

val heavydata: list<string> by lazy {
    log.d(tag, "只在首次访问时执行")
    loadfromdb()          // 耗时操作
}

// 第一次访问触发初始化
println(heavydata.size)
// 第二次访问直接拿缓存,不会再次执行 loadfromdb()
println(heavydata.size)

6.2 线程安全模式

// 默认:synchronized,加锁保证只初始化一次(多线程安全,略有开销)
val a: string by lazy { "a" }

// publication:允许多线程并发初始化,最终取第一次完成的值
val b: string by lazy(lazythreadsafetymode.publication) { "b" }

// none:无任何线程安全保证,最快;仅限单线程确定场景
val c: string by lazy(lazythreadsafetymode.none) { "c" }

6.3 android:by lazy三件套

class mainactivity : appcompatactivity() {

    // 1. viewbinding
    private val binding by lazy { activitymainbinding.inflate(layoutinflater) }

    // 2. 只在用到时才创建的适配器
    private val adapter by lazy {
        orderadapter(onitemclick = { order -> opendetail(order.id) })
    }

    // 3. gson / retrofit 等单例工具
    private val gson: gson by lazy { gsonbuilder().setlenient().create() }
}

7.by属性委托

kotlin 委托语法:val/var 属性 by 委托对象,属性的 get/set 交给委托对象实现。

7.1 标准委托一:lazy(延迟初始化)

见上一节。

7.2 标准委托二:observable(监听变化)

var score: int by delegates.observable(0) { prop, old, new ->
    // 每次赋值后回调(无法拦截)
    log.d(tag, "${prop.name}: $old -> $new")
}

score = 90   // 输出 score: 0 -> 90

7.3 标准委托三:vetoable(可否决的赋值)

var age: int by delegates.vetoable(0) { _, old, new ->
    new >= 0          // 返回 false 则本次赋值被拒绝
}

age = 25    // 生效
age = -5    // 被拒绝,age 仍是 25

7.4 标准委托四:delegates.notnull()(延迟赋值 + 非空)

var token: string by delegates.notnull()

fun settoken(t: string) { token = t }

fun use() {
    // 未赋值就读取会抛 illegalstateexception,比可空类型更安全
    println(token.length)
}

7.5 委托给 map(适合解析 json map)

class config(map: map<string, any?>) {
    val host: string by map
    val port: int by map
}

val cfg = config(mapof("host" to "192.168.2.40", "port" to 1680))
println(cfg.host)   // 192.168.2.40
println(cfg.port)   // 1680

7.6 接口委托(by而不是属性)

interface logger {
    fun log(msg: string)
    fun logerror(e: throwable)
}

class defaultlogger : logger {
    override fun log(msg: string) = println("[info] $msg")
    override fun logerror(e: throwable) = println("[error] $e")
}

// 只需要重写一部分,其余全部转发给 impl
class orderviewmodel(private val impl: logger = defaultlogger()) : logger by impl {
    override fun logerror(e: throwable) {
        super.logerror(e)            // 转发给被委托对象
        crashreporter.report(e)      // 额外增强
    }
}

7.7 自定义委托(实现readwriteproperty/readonlyproperty)

// 场景:sharedpreferences 属性化读写
class preferencedelegate<t>(
    private val prefs: sharedpreferences,
    private val key: string,
    private val default: t
) : readwriteproperty<any?, t> {

    @suppress("unchecked_cast")
    override fun getvalue(thisref: any?, property: kproperty<*>): t =
        when (default) {
            is string -> prefs.getstring(key, default) as t
            is int -> prefs.getint(key, default) as t
            is boolean -> prefs.getboolean(key, default) as t
            is long -> prefs.getlong(key, default) as t
            else -> error("不支持的类型: ${default!!::class.java}")
        }

    override fun setvalue(thisref: any?, property: kproperty<*>, value: t) {
        prefs.edit().apply {
            when (value) {
                is string -> putstring(key, value)
                is int -> putint(key, value)
                is boolean -> putboolean(key, value)
                is long -> putlong(key, value)
                else -> error("不支持的类型")
            }
        }.apply()
    }
}

// 使用
class settings(context: context) {
    private val prefs = context.getsharedpreferences("app", context.mode_private)

    var isdarkmode: boolean by preferencedelegate(prefs, "dark_mode", false)
    var username: string by preferencedelegate(prefs, "user_name", "guest")
}

val s = settings(context)
s.isdarkmode = true                       // 自动写入 sp
println(s.isdarkmode)                     // 自动读取

8.by在 android 中的实战

8.1by viewmodels()/by activityviewmodels()

class orderfragment : fragment(r.layout.fragment_order) {

    // 作用域绑定 fragment,配置变更不重建
    private val viewmodel: orderviewmodel by viewmodels()

    // 作用域绑定宿主 activity(fragment 之间共享数据)
    private val sharedviewmodel: sharedviewmodel by activityviewmodels()

    // 需要工厂时
    private val vm: orderviewmodel by viewmodels {
        orderviewmodelfactory(repository)
    }
}

需要额外依赖:implementation "androidx.fragment:fragment-ktx:1.x.x"

8.2by lazy+ viewbinding

class orderfragment : fragment(r.layout.fragment_order) {
    private var _binding: fragmentorderbinding? = null
    private val binding get() = _binding!!

    override fun oncreateview(...): view {
        _binding = fragmentorderbinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun ondestroyview() {
        super.ondestroyview()
        _binding = null     // fragment 视图销毁必须置空,否则内存泄漏
    }
}

8.3by preference()(androidx.preference)

class settingsfragment : preferencefragmentcompat() {

    val nickname: string by preference("nickname", "guest")

    override fun oncreatepreferences(savedinstancestate: bundle?, rootkey: string?) {
        setpreferencesfromresource(r.xml.settings, rootkey)
    }
}

8.4by lazy+ kotlin 单例(object天然线程安全)

val retrofit: retrofit by lazy {
    retrofit.builder()
        .baseurl(baseconfig.base_url)          // 例如 http://192.168.2.40:1680/api/q5-bill/
        .addconverterfactory(gsonconverterfactory.create())
        .addcalladapterfactory(rxjava3calladapterfactory.create())
        .client(okhttpclient)
        .build()
}

9. 其他高频工具函数

9.1takeif/takeunless

// takeif: 条件成立返回对象本身,否则返回 null
val validage = age.takeif { it in 0..150 }

// 结合 ?.let 使用,替代 if-else
userinput.takeif { it.isnotblank() }?.let { submit(it) }

// takeunless: 与 takeif 相反,条件不成立才返回对象
val file = file(path).takeunless { it.isdirectory }

9.2runcatching(替代 try-catch)

val result = runcatching {
    // 可能抛异常的代码
    val json = api.getorder(id)
    parse(json)
}

result
    .onsuccess { order -> render(order) }
    .onfailure { e -> showerror(e.message) }

// 取值:getordefault / getornull / getorelse
val order = result.getornull()
val safe = result.getorelse { order.empty() }

9.3use(自动关闭资源,类似 java try-with-resources)

fileinputstream(file).use { input ->
    val bytes = input.readbytes()
    parser.parse(bytes)
}   // 块结束自动 close,异常也会关闭

// 一次性发送请求的场景
httpurlconnection(url).apply {
    connecttimeout = 5000
}.use { conn ->
    conn.inputstream.bufferedreader().readtext()
}

9.4measuretimemillis/measurenanotime(性能计时)

val cost = measuretimemillis {
    formulas.foreach { it.evaluate() }
}
log.d(tag, "公式计算耗时:${cost}ms")

9.5repeat(固定次数循环)

repeat(3) { index ->
    log.d(tag, "第 ${index + 1} 次重试")
}

9.6isinitialized(lateinit安全检查)

private lateinit var adapter: orderadapter

fun refresh() {
    if (::adapter.isinitialized) adapter.notifydatasetchanged()
}

以上就是android kotlin开发中常用函数使用手册的详细内容,更多关于android kotlin常用函数的资料请关注代码网其它相关文章!

赞 (0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com