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

时间:2017-05-22 09:16:51

标签: android kotlin

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

所以实际上我必须写这样的东西(官方推荐谷歌):

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。 我在互联网上找到的是一名官员blog post,表示自2013年2月以来不可能。

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

4 个答案:

答案 0 :(得分:3)

这里有两个问题。

首先,您错误地认为在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
}

或使用?.?: null运算符与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

的原因

答案 1 :(得分:0)

Kotlin支持的可变参数。

我想推荐你discussion in kotlinlang.org

答案 2 :(得分:0)

官方说来,您不能覆盖方法参数。你能做的最好的就是“影子”param变量。

所以你可以这样做(不知道为什么你会想要阴影,但你可以)

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

答案 3 :(得分:-1)

实现这一目标有一种肮脏但有用的方法。

fun a(b: Int) {
   var b = b
   b++ // this compiles
}