Kotlin全局变量后置初始化

问题

开源的雨燕输入法项目已经切换成Kotlin语言进行开发。
代码切换完成后,在重构代码时发现,使用Kotlin语言定义全局变量(包括View对象),默认只均为null
这就导致所有使用该变量的调用均需进行判空(?.!!)操作,满足 Kotlin 的空指针检查,哪怕已经明确该变量此时不会为null
此时就需要使用关键字lateinit救场了。

优化前

代码未优化前,创建变量及调用方式如下。

  • 创建全局变量mSkbRoot,初始值为null

    var mSkbRoot: RelativeLayout? = null
    
  • 代码中为全局变量mSkbRoot赋值。

    mSkbRoot = LayoutInflater.from(context).inflate(R.layout.sdk_skb_container, this, false) as RelativeLayout
    
  • 使用全局变量,需进行空指针检查。

    mIvSkbMove = mSkbRoot!!.findViewById(R.id.iv_keyboard_move)
    mSkbRoot?.background = activeTheme.backgroundGradientDrawable(isKeyBorder)
    

    若未检查空指针,编辑器会报错:

    Smart cast to 'RelativeLayout' is impossible, because 'mSkbRoot' is a mutable property that could have been changed by this time
    

优化后

lateinit关键字用于延迟属性初始化,通知编译器该变量会在后续进行初始化,不用在定义时为其赋值null
lateinit可以对可变、非空、非基本数据类型进行修饰。
使用lateinit修饰后,我们就可以像Java类似的调用。

  • 创建全局变量,mSkbRoot,使用lateinit修饰。

    lateinit var mSkbRoot: RelativeLayout
    
  • 为全局变量mSkbRoot赋值。

    mSkbRoot = LayoutInflater.from(context).inflate(R.layout.sdk_skb_container, this, false) as RelativeLayout
    
  • 使用全局变量,无需空指针检查。

    mIvSkbMove = mSkbRoot.findViewById(R.id.iv_keyboard_move)
    mSkbRoot.background = activeTheme.backgroundGradientDrawable(isKeyBorder)
    

问题记录

  • 异常风险。
    通过lateinit可以实现延迟对变量进行初始化,但该方式同时会带来未及是对变量初始化,而直接调用变量导致的异常UninitializedPropertyAccessException

  • 判空操作失效。
    优化前,我们可以对全局变量进行判空操作:

    if (mSkbRoot == null) {
        // 初始化操作
    }
    

    但是一旦使用lateinit关键字修饰后,该判断会失效:Condition 'mSkbRoot == null' is always 'false'
    此时该变量不为null,但是未进行初始化,我们需要对变量判断是否进行初始化:

    if (::mSkbRoot.isInitialized) {
        // 初始化操作
    }
    

   转载规则


《Kotlin全局变量后置初始化》 gure 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
生活会有遗憾但还要继续 生活会有遗憾但还要继续
连续三天几乎没有做什么工作,早出晚归,忙侄女高考志愿填报的事情。 三天来,我仔细研读评估志愿填报规则、一个个筛选本科院校优劣势、既往录取名次、趋势,发现很多以前一知半解的高考常识和志愿误解。 我终于明白了高考招生的规则和志愿投递的原理。我连
2024-06-28
下一篇 
使用Gradle获取Git记录 使用Gradle获取Git记录
问题开源的雨燕输入法项目中,在关于界面要实现显示Git提交记录以及点击条目跳转到对应的Github提交节点。之前的方案是,在每次打包前手动更改对应的值,不但麻烦,且易出错。技术上分析,一旦打包完成,应用内不具备Git环境,因此没办法通过Ja
2024-06-24
  目录