Application是Android的又一大组件,在App运行过程中,有且仅有一个Application对象贯穿应用的整个生命周期,所以适合在Application中保存应用运行时的全局变量。而开展该工作的基础,是必须获得Application对象的唯一实例,也就是将Application单例化。获取一个类的单例对象,需要运用程序设计中常见的单例模式,倘若通过Java编码实现单例化,想必早已是大家耳熟能详的了。下面便是个Application单例化的Java代码例子:

public class MainApplication extends Application {private static MainApplication mApp;public static MainApplication getInstance() {return mApp;}    @Overridepublic void onCreate() {super.onCreate();mApp = this;}
}

从上可见这个单例模式的实现过程主要有三个步骤,说明如下:
1、在自定义的Application类内部声明一个该类的静态实例;
2、重写onCreate方法,把自身对象赋值给第一步声明的实例;
3、提供一个供外部调用的静态方法getInstance,该方法返回第一步声明的Application类实例;
不管是代码还是步骤,这个单例化的实现都还蛮简单的。同样的单例化过程通过Kotlin编码实现的话,静态属性和静态方法可利用伴生对象来实现,这样就形成了Kotlin单例化的第一种方式:手工声明属性的单例化,具体描述见下。

一、手工声明属性的单例化

该方式与Java的常见做法一致,也是手工声明自身类的静态实例,然后通过静态方法返回自身实例。与Java的不同之处在于:Kotlin引入了空安全机制,故而静态属性要声明为可空变量、然后获得实例时要在末尾加上双感叹号表示非空,当然也可事先将自身实例声明为延迟初始化属性。总之,两种声明手段都是为了确保一个目的,即Application类提供给外部访问的自身实例必须是非空的。
下面是手工单例化的Kotlin代码例子:

class MainApplication : Application() {override fun onCreate() {super.onCreate()instance = this}//单例化的第一种方式:声明一个简单的Application属性companion object {//情况一:声明可空的属性private var instance: MainApplication? = nullfun instance() = instance!!//情况二:声明延迟初始化属性//private lateinit var instance: MainApplication//fun instance() = instance}
}

二、借助Delegates的委托属性单例化

第一种方式的单例化,虽然提供了两种属性的声明手段,但只是为了保证自身实例的非空性。如果仅仅是确保属性非空,其实Kotlin已经提供了一个系统工具进行自动校验,这个工具便是Delegates的notNull方法。该方法返回非空校验的行为,只要将指定属性的读写行为委托给这个非空校验行为,那么开发者就无需手工进行非空判断了。利用Delegates工具的属性代理功能,就构成了Kotlin的第二种单例化方式;有关委托属性和属性代理的介绍,可参见前面的博文《Kotlin入门(25)共享参数模板》。
下面是系统委托属性单例化的Kotlin代码例子:

class MainApplication : Application() {override fun onCreate() {super.onCreate()instance = this}//单例化的第二种方式:利用系统自带的Delegates生成委托属性companion object {private var instance: MainApplication by Delegates.notNull()fun instance() = instance}
}

第二种方式的委托属性单例化,在App代码中获取Application实例与第一种方式是一样的,都是调用“MainApplication.instance()”这个函数获得Application的自身实例。

三、自定义委托行为的单例化

前两种单例化都只完成了非空校验,还不是严格意义上的单例化。真正的单例化是有且仅有一次赋值操作,尽管前两种的单例化并未实现唯一赋值功能,但是在大多数场合已经够用了。可是作为孜孜不倦的开发者,务必要究根问底,到底能不能实现唯一赋值情况下的单例化。显然系统自带的Delegates工具没有提供大家期待的校验行为,于是开发者必须自己写一个能够校验赋值次数的行为类,目的是接管委托属性的读写行为。自定义接管行为的实现,前面的博文《Kotlin入门(25)共享参数模板》即已给出了Preference<T>的完整源码,其中关键是重写了读方法getValue和写方法setValue,因此在这里可借鉴Preference<T>完成自定义的委托行为编码。
下面是自定义委托行为的单例化代码:

class MainApplication : Application() {override fun onCreate() {super.onCreate()instance = this}//单例化的第三种方式:自定义一个非空且只能一次性赋值的委托属性companion object {private var instance: MainApplication by NotNullSingleValueVar()fun instance() = instance}//定义一个属性管理类,进行非空和重复赋值的判断private class NotNullSingleValueVar<T>() : ReadWriteProperty<Any?, T> {private var value: T? = nulloverride fun getValue(thisRef: Any?, property: KProperty<*>): T {return value ?: throw IllegalStateException("application not initialized")}override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {this.value = if (this.value == null) valueelse throw IllegalStateException("application already initialized")}}
}

由上述代码看到,自定义的委托行为在getValue方法中进行非空校验,在setValue方法中进行重复赋值的校验,从而按照要求接管了委托属性的读写行为。

点此查看Kotlin入门教程的完整目录

__________________________________________________________________________
打开微信扫一扫下面的二维码,或者直接搜索公众号“老欧说安卓”添加关注,更快更方便地阅读技术干货。

Kotlin入门(28)Application单例化相关推荐

  1. Kotlin入门(18)利用单例对象获取时间

    前面介绍了,使用扩展函数可以很方便地扩充数组Array的处理功能,例如交换两个数组元素.求数组的最大元素等等.那么除了数组之外,日期和时间的相关操作,也是很常见的,比如获取当前日期,获取当前时间.获取 ...

  2. Kotlin入门教程——目录索引

    Kotlin是谷歌官方认可的Android开发语言,即将发布的Android Studio 3.0版本也会开始内置Kotlin,所以未来在App开发中Kotlin取代Java是大势所趋,就像当初And ...

  3. python编程入门单例_常见的在Python中实现单例模式的三种方法

    单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源.如果希望在 ...

  4. 致Android开发者的Kotlin入门

    Google在今年的IO大会上宣布,将Android开发的官方语言更换为Kotlin,作为跟着Google玩儿Android的人,我们必须尽快了解和使用Kotlin语言. 不过Kotlin毕竟是语言级 ...

  5. 设计模式--单例模式--静态内部类和枚举单例

    双重检测锁模式 作用:这个模式通过将同步内容(synchronized内的内容)提到if方法内部,通过双重检测的方式来保证第一次创建的准确性,但是对于后面的再次调用不再要求上锁.从而提高了执行的效率, ...

  6. Android学习-Kotlin语言入门-变量、函数、语法糖、when、for-in、主构造函数、单例类、函数式API、集合遍历、隐式Intent、Activity生命周期、四种启动模式、标准函数

    探究java语言的运行机制 变量.函数.语法糖 when条件语句 for循环 主构造函数.次构造函数 数据类和单例类 集合的创建与遍历 集合的函数式API 创建菜单 隐式使用Intent Activi ...

  7. 【Kotlin】Kotlin 单例 ( 懒汉式 与 恶汉式 | Java 单例 | Kotlin 单例 | 对象声明 | 伴生对象 | get 方法 | ? 与 !! 判空 )

    文章目录 I . 单例的懒汉式与恶汉式 II . Java 中的懒汉式与恶汉式 III . Kotlin 中对应 Java 的懒汉式与恶汉式 IV . Kotlin 对象 ( object ) 声明 ...

  8. python编程入门单例_Python单例模式实例详解

    本文实例讲述了Python单例模式.分享给大家供大家参考,具体如下: 单例模式:保证一个类仅有一个实例,并提供一个访问他的全局访问点. 实现某个类只有一个实例的途径: 1,让一个全局变量使得一个对象被 ...

  9. export function函数传参_04 js高阶函数(惰性函数、柯里化函数、compose函数)和单例设计模式...

    高阶函数的定义 在<javascript设计模式和开发实践>中是这样定义的. 函数可以作为参数被传递: 函数可以作为返回值输出. 结合这两个特点,首先想到的肯定是回调函数,回调函数也是高阶 ...

最新文章

  1. R语言pmax函数和pmin函数按位计算向量最大值、最小值实战
  2. 编程心法 之什么是MVP What is MVP development?
  3. redis install note
  4. AlarmManager使用注意事项
  5. 【HDU - 3746 】Cyclic Nacklace (KMP,最小循环节问题)
  6. 解决ViewPager添加点击监听器无触发的问题
  7. 使用Service Installer在.NET Core中配置依赖注入而无需任何代码
  8. 用Github做一个静态网页(GithubPages)
  9. FortiGate设备管理
  10. 【代码源 Div1 - 105】#451. Dis(倍增求LCA)
  11. (风中奇缘) Pocahontas
  12. js 对象中属性的来源
  13. ImageAI 学习
  14. 获取某年某月的第一天是星期几
  15. 海马玩模拟器离线安装包下载方法
  16. centos7.2php,Centos7.2之phpadmin安装配置
  17. 如何修改jadx的默认内存
  18. JZOJ5939. 【NOIP2018模拟10.30】阻击计划
  19. 美通社企业新闻汇总 | 2019.2.26 | 华为企业业务首登MWC发布数字平台;爱茉莉与屈臣氏达成战略合作...
  20. python中重采样的时间间隔与等距,resample,periods

热门文章

  1. 关于delete字符串 需不需要加 [ ]
  2. CCF 2017-3-2 学生排队
  3. 西瓜书+实战+吴恩达机器学习(十六)半监督学习(半监督SVM、半监督k-means、协同训练算法)
  4. 进程和线程的区别, 面相对象补充, 进程, 数据共享, 锁, 进程池, 爬虫模块(requests, bs4(beautifulsoup))...
  5. 1、Fiddler的基本介绍
  6. linux重启后mysql无法启动_Linux重启后MySQL数据库文件全部丢失MySQL无法启动
  7. 双精度浮点数转换_模型压缩一半,精度几乎无损,TensorFlow推出半精度浮点量化工具包,还有在线Demo...
  8. 若依图片上传成功不能显示的解决办法?
  9. Docker安装RabbitMQ教程
  10. 最新战火互娱JS逆向分析实战教程