96人参与 • 2026-09-22 • Android
涵盖:作用域函数(let / run / with / apply / also)、委托(by)、惰性初始化(lazy)、 以及 takeif、runcatching、use 等高频工具函数。
签名:inline fun <t, r> t.let(block: (t) -> r): r
对非空对象执行操作,并可改变返回类型。
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" } ?: "昵称:未设置"
// 避免写两次耗时函数
getusername()?.let { n ->
println("你好,$n")
cache.put("name", n)
}
val length: int? = listof("a", "bb", "ccc")
.firstornull { it.length > 1 }
.let { it?.length ?: 0 }
val result = calculatetotal().let { total ->
// total 只在这个块内可见,避免污染外部作用域
if (total > 1000) total * 0.9 else total
}
binding.btnsubmit.setonclicklistener {
viewmodel.submit()?.let { state ->
toast.maketext(this, state.message, toast.length_short).show()
}
}
签名
inline fun <r> run(block: () -> r): r // 非扩展:开一个新作用域 inline fun <t, r> t.run(block: t.() -> r): r // 扩展:接收者是 this
val user: user? = repository.finduser(id)
val summary = user?.run {
// 这里 this 就是 user,属性可省略 this.
"$name($age 岁)"
} ?: "用户不存在"
val padding = run {
val base = resources.getdimensionpixelsize(r.dimen.base)
val half = base / 2
half * 3 // 最后一行就是 run 的返回值
}
private fun buildquery(): map<string, string> = run {
val page = currentpage + 1
val size = pagesize.coerceatmost(50)
mapof("page" to "$page", "size" to "$size")
}
fun showemptystate() {
binding.emptyview.run {
isvisible = true
text = getstring(r.string.empty_tip)
setonclicklistener { viewmodel.reload() }
}
}
签名:inline fun <t, r> with(receiver: t, block: t.() -> r): r
注意:with 不是扩展函数,它是普通函数,接收者作为第一个参数传入。
val sb = stringbuilder()
with(sb) {
append("hello")
append(", ")
append("kotlin")
}
println(sb.tostring()) // hello, kotlin
with(binding.recyclerview) {
layoutmanager = linearlayoutmanager(context)
adapter = orderadapter
sethasfixedsize(true)
additemdecoration(divideritemdecoration(context, divideritemdecoration.vertical))
}
val detail = with(requirearguments()) {
detailargs(
id = getstring("id") ?: "",
from = getstring("from") ?: "unknown",
editable = getboolean("editable", false)
)
}
// 两者等价,写法差异:
with(user) { println(name) } // with(user) { ... }
user.run { println(name) } // user.run { ... }
// 习惯:可空对象用 ?.run {},非空对象用 with(x) {} 更直观
签名:inline fun <t> t.apply(block: t.() -> unit): t
返回对象本身,块内 this 是对象,适合"创建即配置"。
val intent = intent(context, detailactivity::class.java).apply {
putextra("id", orderid)
putextra("from", "list")
flags = intent.flag_activity_new_task
}
startactivity(intent)
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()
val request = orderrequest().apply {
userid = uid
page = 1
pagesize = 20
sort = "createtime,desc"
}
val text = textview(context).apply {
this.text = "标题" // 与属性名冲突时用 this 区分
textsize = 16f
settextcolor(color.black)
gravity = gravity.center
}.text.tostring()
apply 里如果省略 this.,要注意「参数名/属性名同名」的遮蔽问题。
签名:inline fun <t> t.also(block: (t) -> unit): t
返回对象本身,块内用 it,非常适合插入副作用而不打断链式调用。
val order = repository.createorder(req)
.also { log.d(tag, "创建订单成功: ${it.id}") }
.also { analytics.track("order_created", mapof("id" to it.id)) }
val file = file(path)
.also { require(it.exists()) { "文件不存在: $path" } }
.also { require(it.canread()) { "文件不可读" } }
// apply:配置对象内部,省略 this
val user = user().apply {
name = "tom" // 等价 this.name = "tom"
}
// also:对外部变量做副作用,必须用 it
val user = user().also {
it.name = "tom" // 必须写 it.name
loguser(it) // 副作用:记录日志
}
签名:fun <t> lazy(initializer: () -> t): lazy<t>
第一次访问才初始化,之后复用缓存值。
val heavydata: list<string> by lazy {
log.d(tag, "只在首次访问时执行")
loadfromdb() // 耗时操作
}
// 第一次访问触发初始化
println(heavydata.size)
// 第二次访问直接拿缓存,不会再次执行 loadfromdb()
println(heavydata.size)
// 默认: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" }
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() }
}
kotlin 委托语法:val/var 属性 by 委托对象,属性的 get/set 交给委托对象实现。
见上一节。
var score: int by delegates.observable(0) { prop, old, new ->
// 每次赋值后回调(无法拦截)
log.d(tag, "${prop.name}: $old -> $new")
}
score = 90 // 输出 score: 0 -> 90
var age: int by delegates.vetoable(0) { _, old, new ->
new >= 0 // 返回 false 则本次赋值被拒绝
}
age = 25 // 生效
age = -5 // 被拒绝,age 仍是 25
var token: string by delegates.notnull()
fun settoken(t: string) { token = t }
fun use() {
// 未赋值就读取会抛 illegalstateexception,比可空类型更安全
println(token.length)
}
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
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) // 额外增强
}
}
// 场景: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) // 自动读取
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"
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 视图销毁必须置空,否则内存泄漏
}
}
class settingsfragment : preferencefragmentcompat() {
val nickname: string by preference("nickname", "guest")
override fun oncreatepreferences(savedinstancestate: bundle?, rootkey: string?) {
setpreferencesfromresource(r.xml.settings, rootkey)
}
}
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()
}
// 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 }
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() }
fileinputstream(file).use { input ->
val bytes = input.readbytes()
parser.parse(bytes)
} // 块结束自动 close,异常也会关闭
// 一次性发送请求的场景
httpurlconnection(url).apply {
connecttimeout = 5000
}.use { conn ->
conn.inputstream.bufferedreader().readtext()
}
val cost = measuretimemillis {
formulas.foreach { it.evaluate() }
}
log.d(tag, "公式计算耗时:${cost}ms")
repeat(3) { index ->
log.d(tag, "第 ${index + 1} 次重试")
}
private lateinit var adapter: orderadapter
fun refresh() {
if (::adapter.isinitialized) adapter.notifydatasetchanged()
}
以上就是android kotlin开发中常用函数使用手册的详细内容,更多关于android kotlin常用函数的资料请关注代码网其它相关文章!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论