android - 如何在 Kotlin 中使方法参数可变?

标签 android kotlin

我正在 Android 项目中实现一个 SpinnerAdapter。所以我必须重写 getView(i: Int, convertView: View, parent: ViewGroup) 方法。所以 convertView 在这里是为了重用现有 View 并减少内存使用和 GC 发生。因此,如果它是 null,我必须创建 View 并使用已经创建的 View 。

所以实际上我必须写这样的东西(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 不允许写入参数。 我在网上查到的是官方blog post这表示自 2013 年 2 月以来不可能。

所以我想知道是否有任何解决方法?

最佳答案

这里有两个问题。

首先,您错误地假设在 Java 中修改 view 会在当前函数范围之外执行任何操作。它不是。您将该参数设置为新值不会影响局部函数范围之外的任何内容。

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
   }
}

或者避免新的局部变量:

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) }
   }
}

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
}

或使用 ?.?: 空运算符结合 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))
                }
}

还有另外 10 种变体,但您可以尝试看看自己喜欢什么。

通过使用相同的名称来隐藏变量被认为不是一个好的做法(但允许),这就是为什么它是一个编译器警告。以及为什么您看到上面的变量名从 view 更改为 tempView

关于android - 如何在 Kotlin 中使方法参数可变?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44109098/

相关文章:

gradle - gradle构建测试时如何执行一些代码

postgresql - Spring Boot 2.1.4 + JDBI + HikariCP + PostgreSQL 发生错误后连接未释放到池

android - 使用 Play 核心库验证非 Google Play 应用安装

Android - 调用 Activity 完成后获取 Activity 结果

android - lateinit RecyclerView是否需要在quickstart-android数据库应用中初始化?

android - kotlin如何通过delegate使用this来实例化viewmodel

kotlin - 控制 Kotlin DSL 构建器中的范围

java - android java同时从不同线程读/写textview

android - 发布 Alpha 新 Android 游戏时如何将 "Link App"转换为现有客户端 ID 和生产 SHA1

带有小端错误颜色格式的Android平板电脑