用Kotlin在android中声明UI组件的最好方法是什么?

我正在尝试使用Kotlin第一次构建Android应用程序。

我想在OnCreate方法之外的某些按钮上声明,我只能初始化它们在这个函数中使用findViewById。

我可以声明简单和干净的代码,如在Java中?

private Button btnProceed; 

因为当它转换成Kotlin它看起来像:

 private var btnProceed: Button? = null 

然后当初始化OnClick函数需要添加! 标志:

 btnProceed!!.setOnClickListener 

什么是正确和最清洁的方式?

对于lateinit这是一个很好的用例。 标记一个属性lateinit允许你使它不能为空,但是在你的Activity的构造函数被调用的时候不给它赋值。 当Activity初始化发生在一个单独的初始化方法中时,比正在运行的构造函数(在本例中为onCreate )更精确。

 private lateinit var btnProceed: Button 

如果在为其分配实际值之前读取了属性,则会在运行时抛出一个异常 – 通过使用lateinit ,您将在第一次访问它之前负责初始化它。


否则,如果您希望编译器保证您可以安全访问,则可以使默认情况下的Button空。 而不是不安全!! 但是,转换器经常使用的操作员 ,您应该在您访问该财产的地方使用安全呼叫操作员 :

 btnProceed?.setOnClickListener { ... } 

如果btnProceed是一个非空值,这将进行常规调用,否则不做任何事情。


最后,您可以查看Kotlin Android扩展程序 ,该程序不需要为您的View完全创建属性(如果它适用于您的项目)。


上次编辑(现在):你也应该看看在other answers所描述的使用lazy 。 懒惰很酷。

而不是使用lateinit ,你也可以做延迟初始化 :

 private val button by lazy { findViewById(R.id.button) as Button } 

第一次访问button属性时,它将执行一次该块并将结果用于将来的调用。 例如,在onCreate中,您现在可以直接访问它:

 fun onCreate(savedInstanceState: Bundle?) { super.onCreate(bundle) setContentView(R.layout.my_view) button.setOnClickListener { ... } } 

你可以使用@ zsmb13的建议来实现,但是这样做的缺点是你的视图是可变的而不是最终的。 如果你希望他们是最终的,你可以使用lazy属性委托

通过使用lazy你可以声明当你第一次尝试通过声明来访问它时,值是如何被初始化的

 private val btnProceed: Button by lazy { findViewById(R.id.yourID) } 

每当你访问你的btnProceed你将会有你的活动(这个例子假设你正在使用一个活动)加载,所以你可以使用该方法