如何使用 kotlin 在 android 中初始化小部件

Posted

技术标签:

【中文标题】如何使用 kotlin 在 android 中初始化小部件【英文标题】:How to initialize widgets in android using kotlin 【发布时间】:2016-09-27 13:58:42 【问题描述】:

我已经开始学习在 android 中使用 kotlin 语言并在初始化我的按钮变量时遇到问题,因为在定义我的变量时它要求在我使用 null 值初始化并在 oncreate 函数中绑定变量时给出一些初始值它给了

kotlin.KotlinNullPointerException

这是我的代码

class AddsFragment : Fragment() 

    var Add: Button = null!!

    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? 
        val Rootview = inflater!!.inflate(R.layout.clubsfragment, null, false)
        Add = Rootview.findViewById(R.id.add) as Button
        return Rootview
    

【问题讨论】:

【参考方案1】:

!! 操作符检查接收者是否为null,如果是则抛出KotlinNullPointerException。所以null!! 总会抛出异常。

您可以通过以下方式实现您想要的:

    将属性类型设置为Button?。在这种情况下,当访问按钮的方法时,您必须使用 ?!!

    var add: Button? = null
    // Initialize it somewhere.
    
    add?.setText("Text") // Calls setText if Add != null
    add!!.setText("Text") // Throws an exception if Add == null
    

    将按钮设为lateinit 属性。

    lateinit var add: Button
    

    将按钮设为notNull 委托属性。

    var add: Button by Delegates.notNull()
    

在最后两种情况下,您无法检查按钮是否为null。如果您需要 null 比较来处理变量,请使用第一种方法。


还有另一种方法,我不会在这个答案中详细描述。第一个是使用Kotlin Android Extensions。这是一个编译器插件,可为您的视图生成合成属性,因此您无需调用 findViewById() 并可以使用生成的属性访问视图。

第二种方法是创建您自己的委托,该委托将为您调用findViewById()。它可能看起来像这样:

val add: Button by bindView(R.id.add)

您可以在 KotterKnife 项目中找到此类委托的示例。

【讨论】:

那么我该如何初始化我的变量??【参考方案2】:

可以使用 Kotlin 编写 helper bind 函数:

fun <T : View> Activity.bind(@IdRes res : Int) : Lazy<T> 
    @Suppress("UNCHECKED_CAST")    
    return lazy  findViewById(res) as T 

然后您可以使用val(在Java 中等于final)简单地定义一次变量:

class MyActivity : AppCompatActivity() 
    private val button: Button by bind(R.id.button)

class MyActivity : AppCompatActivity() 
    private val button by bind<Button>(R.id.button)

【讨论】:

【参考方案3】:

您可以使用以下任何一种方法在 kotlin 中初始化视图:

1.可空变量

private var textView: TextView? = null
…
textView = findViewById(R.id.text_view) as TextView

2。延迟初始化

private lateinit var textView: TextView
…
textView = findViewById(R.id.text_view) as TextView

3. Delegates.notNull()

private var textView: TextView by Delegates.notNull()
…
textView = findViewById(R.id.text_view) as TextView

4.惰性属性

private val textView: TextView by lazy  findViewById(R.id.text_view) as TextView 

5.黄油刀

@BindView(R2.id.text_view)
internal lateinit var textView: TextView

6.小刀

private val textView: TextView by bindView(R.id.text_view)

7. Kotlin Android 扩展

没有代码示例,只需添加正确的导入并开始使用合成生成的属性,如下所示。

import kotlinx.android.synthetic.main.<layout>.*

8. Android 数据绑定

binding = FragmentLayoutBinding.inflate(inflater, container, false)
...
binding.textView.text = "Hello"

您可以在Pros/cons of Android view access strategies查看每种方法的优缺点

【讨论】:

以上是关于如何使用 kotlin 在 android 中初始化小部件的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Kotlin 中为 Android 的 RecyclerView 适配器初始化 viewHolder

如何在 Kotlin 类中声明一个公共值 (val) 以便稍后对其进行初始化。在这种特殊情况下不能使用 var

使用 Kotlin 在 android 中声明 UI 组件的最佳方法是啥?

Android开发-kotlin基本使用(一)

RecyclerView 动画问题 Android Kotlin

如何强制客户端代码使用合约初始化 Kotlin 中所有必需的构建器字段?