class MainActivity : AppCompatActivity(), View.OnClickListener {
private var adapter: MsgAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
...
adapter = MsgAdapter(msgList)
...
}
override fun onClick(v: View?) {
...
adapter?.notifyItemInserted(msgList.size - 1)
...
}
}
全局变量adapter的初始化在onCreate()方法中, 所以要先将adapter赋值为null, 同时把它的类型声明成MsgAdapter?
虽然adapter会在onCreate()方法中被初始化, 且能确保onClick()方法必然在onCreate()方法之后才会调用, 但是在onClick()方法中调用adapter的任何方法时仍然要进行判空处理, 否则无法通过编译.
当代码中的全局变量实例越来越多时, 为了满足Kotlin编译器的要求, 需要编写大量额外的判空处理代码.
可以通过延迟初始化来解决这个问题.
延迟初始化使用lateinit关键字, 代码如下:
class MainActivity : AppCompatActivity(), View.OnClickListener {
private lateinit var adapter: MsgAdapter
override fun onCreate(savedInstanceState: Bundle?) {
...
adapter = MsgAdapter(msgList)
...
}
override fun onClick(v: View?) {
...
adapter.notifyItemInserted(msgList.size - 1)
...
}
}
如此, 因为在变量前加上了lateinit
关键字, 就可以不用初始化为null, 同时类型声明也可以改成MsgAdapter
. 因为MsgAdapter
是非空类型, 所以在onClick()方法中也就不需要判空处理了.
在adapter没有初始化的情况下使用, 程序会抛UninitializedPropertyAccessException
异常.
class MainActivity : AppCompatActivity(), View.OnClickListener {
private lateinit var adapter: MsgAdapter
override fun onCreate(savedInstanceState: Bundle?) {
...
if (!::adapter.isInitialized) {
adapter = MsgAdapter(msgList)
}
...
}
}
::adapter.isInitialized
用于判断变量是否已经初始化. !
对结果取反, 若没有初始化, 则进行初始化.
interface Result
class Success(val msg: String) : Result
class Failure(val error: Exception) : Result
fun getResultMsg(result: Result){
when(result)
{
is Success -> result.msg
is Failure -> result.error.message
else -> throw IllegalArgumentException()
}
}
else分支
是为了满足Kotlin编译器的语法检查, 没有else分支
的话, Kotlin编译器会认为条件缺失, 无法编译.
当新增一个Unknown类并实现Result接口, 用于表示未知的执行结果, 但是忘记在getResultMsg()方法中添加对应的条件分支, 编译器在这种情况下不会提醒, 而是进入else分支
.(在其他编程语言也普遍存在)
// 密封类及其所有子类只能定义在同一个文件的顶层位置,不能嵌套在其他类中,这是被密封类底层的实现机制所限制的。
sealed class Result
class Success(val msg: String) : Result()
class Failure(val error: Exception) : Result()
fun getResultMsg(result: Result){
// 当when语句传入一个密封类变量时, Kotlin编译器会自动检查该密封类有哪些子类, ->
// ->并强制要求将所有子类对应的条件处理.这样就不会漏写条件分支.
when(result)
{
is Success -> result.msg
is Failure -> result.error.message
}
}
sealed class MsgViewHolder(view: View) : RecyclerView.ViewHolder(view)
class LeftViewHolder(view: View) : MsgViewHolder(view) {
val leftMsg: TextView = view.findViewById(R.id.leftMsg)
}
class RightViewHolder(view: View) : MsgViewHolder(view) {
val rightMsg: TextView = view.findViewById(R.id.rightMsg)
}
class MsgAdapter(val msgList: List<Msg>) : RecyclerView.Adapter<MsgViewHolder>() {
...
override fun onBindViewHolder(holder: MsgViewHolder, position: Int) {
val msg = msgList[position]
when (holder) {
is LeftViewHolder -> holder.leftMsg.text = msg.content
is RightViewHolder -> holder.rightMsg.text = msg.content
}
}
...
}
郭霖. 《第一行代码 Android 第3版》