使用Kotlin';s在Android(Java)扩展和接口上可为空

使用Kotlin';s在Android(Java)扩展和接口上可为空,android,kotlin,nullpointerexception,Android,Kotlin,Nullpointerexception,我正在努力学习用Android做事情的“Kotlin原生方式”,同时既不是Kotlin、Java,也不是Android开发方面的专家。具体来说,如何正确处理Android界面/扩展中的可空性 下面是一个使用RecyclerView的工作示例的片段,该示例似乎滥用了Kotlin的nullability范例 适配器: 首先,适配器类: class PersonListAdapter(private val list: ArrayList<Person>,

我正在努力学习用Android做事情的“Kotlin原生方式”,同时既不是Kotlin、Java,也不是Android开发方面的专家。具体来说,如何正确处理Android界面/扩展中的可空性

下面是一个使用
RecyclerView
的工作示例的片段,该示例似乎滥用了Kotlin的nullability范例

适配器: 首先,适配器类:

class PersonListAdapter(private val list: ArrayList<Person>,
                        private val context: Context) : RecyclerView.Adapter<PersonListAdapter.ViewHolder>() {
或者,如果这不容易做到,为什么不使用可为空的列表初始化适配器呢?我认为后者无法实现,因为我们正在扩展
RecyclerView.Adapter
,但我想请您确认一下。我的想法如下:

class PersonListAdapter(private val list: ArrayList<Person>?,
                        private val context: Context) : RecyclerView.Adapter<PersonListAdapter.ViewHolder>() {
class PersonListAdapter(私有值列表:ArrayList?,
private val context:context):RecyclerView.Adapter(){
(注意
ArrayList?
而不是
ArrayList


还是有更好的范例

总结 在使用Android接口、扩展和其他我们在Java代码的基础上构建的情况下,处理Kotlin中可空性的正确方法是什么


我真的想尽量避免使用
!!
。虽然我是这个领域的新手,但在我看来,
的重点在于,而使用
!!
本质上就是说,“不,我要回那十亿美元的错误”,不是吗?

这段代码的作者只是没有思考,或者他们也是Kotlin的初学者

只要你需要实例化的对象在其构造函数中不需要工作上下文对象,它就可以在任何方法之外实例化。我知道,当我开始Android开发时,注意到某些东西只能在
onCreate()中实例化
,我选择了安全的路线,只是在那里实例化了所有东西。很可能代码的作者就是这么做的,然后把这个习惯转移到了科特林身上

现在,处理后期init变量的更好方法通常是使用
lateinit
修饰符:

private lateinit var personList: ArrayList<Person>
我只能推测,但我认为作者只是对后期初始化有点着迷。其他两个参数都不能立即初始化,所以这可能只是对列表进行同样操作的反射


不过,公平地说,这里的
!!
并不是真的犯了“十亿美元的错误”返回。列表在
personList!!
的正上方初始化,因此除非在主线程到达适配器初始化之前运行另一个线程,使
personList
再次为null,否则
personList
保证为非null


至于处理空安全的“最佳”方法……嗯,没有。然而,我可以说,在这种情况下,“最佳”方法是这样的:

private val personList = ArrayList<Person>() //this needs to be at the top now
private val adapter by lazy { PersonListAdapter(personList, this) } //by lazy will initialize this variable once it's first referenced and then retain that instance for future calls
private val layoutManager by lazy { LinearLayoutManager(this) }
如果你看一个反编译的Kotlin JVM项目,这实际上就是lazy的
的工作方式。当然,它不在自己的类中,但是Kotlin将创建一个全局变量和一个
getVariable()
方法,该方法与我上面提到的
getInstance()
方法完全相同

整个事情可能会被以下内容所取代:

class SomeSingleton private constructor() {
    companion object {
        val instance by lazy { SomeSingleton() }
    }
}


TL;DR,我只能推测,但作者似乎保留了一些Java编程风格,要么忘记了,要么没有意识到,要么拒绝使用Kotlin替代方案。

太好了,非常感谢!我从未学过Java(但确实知道其他几种语言),所以我进入了Android fresh,Kotlin看起来更友好、更健壮。我真的很感谢解释(1)作者可能在想什么/做什么,(2)Kotlin的本族语应该是什么,(3)提到我那数十亿美元的妄想症可能被夸大了。
getItemCount(): Int = list?.size!! //or list!!.size

val item = list?.get(position)
item?.whatever
private val personList = ArrayList<Person>() //this needs to be at the top now
private val adapter by lazy { PersonListAdapter(personList, this) } //by lazy will initialize this variable once it's first referenced and then retain that instance for future calls
private val layoutManager by lazy { LinearLayoutManager(this) }
class SomeSingleton private constructor() {
    companion object {
        private var instance: SomeSingleton? = null

        fun getInstance(): SomeSingleton {
            if (instance == null) instance = SomeSingleton()
            return instance!! //since technically instance could've been made null from another Thread, Kotlin requires that you assert the non-null state
        }
    }
}
class SomeSingleton private constructor() {
    companion object {
        val instance by lazy { SomeSingleton() }
    }
}