I'm implementing a SpinnerAdapter in Android project. So I have to override getView(i: Int, convertView: View, parent: ViewGroup) method. So convertView is here in order to reuse existing view and reduce memory usage and GC occurrences. So if it is null I have to create view and use already created otherwise.

So in fact I have to write something like this (officially recomended by google):

if (view == null) {
    view = View.inflate(context, R.layout.item_spinner, parent)
    view.tag(Holder(view))
} else {
    (view.tag as Holder).title.text = getItem(i)
}

但是Kotlin不允许写入param.

So I'm wondering if there is any workaround ?

推荐答案

这里有两个问题.

First, you are mistakenly assuming that modifying view in Java does anything outside of the current function scope. It does not. You setting that parameter to a new value affects nothing outside of the local function scope.

View getView(int i, View view, ViewGroup parent) {
   // modify view here does nothing to the original caller reference to view
   // but returning a view does do something
}

接下来,在Kotlin中,所有参数都是final(JVM修饰符,与Java中的final修饰符相同).此代码的Kotlin if语句版本为:

fun getView(i: Int, view: View?, parent: ViewGroup): View {
   return if (view == null) {
       val tempView = View.inflate(context, R.layout.item_spinner, parent)
       tempView.tag(Holder(tempView))
       tempView
   } else { 
       (view.tag as Holder).title.text = getItem(i)
       view
   }
}

or avoiding the new local variable:

fun getView(i: Int, view: View?, parent: ViewGroup): View {
   return if (view == null) {
       View.inflate(context, R.layout.item_spinner, parent).apply {
           tag(Holder(this)) // this is now the new view
       }
   } else { 
       view.apply { (tag as Holder).title.text = getItem(i) }
   }
}

or

fun getView(i: Int, view: View?, parent: ViewGroup): View {
   if (view == null) {
       val tempView = View.inflate(context, R.layout.item_spinner, parent)
       tempView.tag(Holder(tempView))
       return tempView
   } 

   (view.tag as Holder).title.text = getItem(i)
   return view
}

or using the ?. and ?: null operators combined with apply():

fun getView(i: Int, view: View?, parent: ViewGroup): View {
    return view?.apply { 
                (tag as Holder).title.text = getItem(i) 
           } ?: View.inflate(context, R.layout.item_spinner, parent).apply {
                     tag(Holder(this))
                }
}

And there are another 10 variations, but you can experiment to see what you like.

使用相同的名称对变量进行阴影处理被认为是不太好的做法(但被允许),这就是为什么它是一个编译器警告.为什么上面的变量名从view变为tempView

Kotlin相关问答推荐

了解Kotlin函数

在没有外部 map 的情况下转换列表项

如何为集成测试配置Gradle JVM测试套件?

列表在 android WebView 中没有正确迭代

kotlin 父类具有依赖于抽象变量的变量

Kotlin 函数有 2 个参数用于对 Map 或 List 进行排序

从 Kotlin 调用 Java 时可以为空的规则是什么

奇怪的 cotlin check Not Null 参数错误

jetpack compose 将参数传递给 viewModel

如何使用 Kotlin Coroutines 使 setOnClickListener debounce 1 秒?

如何处理 Kotlin 中的异常?

使用 Paging 3 时保存并保留 LazyColumn 滚动位置

更新到版本4.10.1/4.10.2后 Gradle 同步失败

Jetpack Compose State:修改类属性

如何为kotlin异常生成SerialVersionId?

Kotlin中具有多个参数的绑定适配器

生成Kotlin类图

安装 Kotlin-Jupyter:e: java.lang.NoClassDefFoundError: 无法初始化类 org.jetbrains.kotlin.com.intellij.pom.java.LanguageLevel

WebFlux 功能:如何检测空 Flux 并返回 404?

@StringRes、@DrawableRes、@LayoutRes等android注释使用kotlin参数进行判断