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;
} @Override
public 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? = null
fun 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? = null
override 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) value
else throw IllegalStateException("application already initialized")
}
}
}

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

Kotlin入门(28)Application单例化的更多相关文章

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

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

  2. QT中实现应用程序的单例化

    一介绍 通过编写一个QSingleApplication类,来实现Qt程序的单例化,原文的作者是在Windows Vista + Qt4.4 下实现的,不过应用在其他平台上是没问题的.(本文是我在ht ...

  3. OSS - 有关于OSSClient的单例化

    之前在每个控制层OSSClient都是通过新new的方式创建OSSClientBuilder().build(endpoint,accessKeyId,accessKeySecret)进行创建 后期我 ...

  4. Scala入门1(单例对象和伴生类)

    一.Hello World程序的执行原理 参考http://blog.csdn.net/zhangjg_blog/article/details/22760957 object HelloWorld{ ...

  5. 三、singleton(单例化)一个对象的几种方法

    方案一:私有化构造器,通过static final域 @Test public void test13() { A215 a=A215.a; A215 b=A215.a; System.out.pri ...

  6. 28.C++- 单例类模板(详解)

    单例类 描述 指在整个系统生命期中,一个类最多只能有一个实例(instance)存在,使得该实例的唯一性(实例是指一个对象指针)  , 比如:统计在线人数 在单例类里,又分为了懒汉式和饿汉式,它们的区 ...

  7. WPF整理-Mutex确保Application单例运行

    有时我们不希望我们的WPF应用程序可以同时运行有多个实例,当我们试图运行第二个实例的时候,已经运行的实例也应该弹出来. 我们可以用Mutex来实现 打开App.xaml.cs,在App类中添加如下内容 ...

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

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

  9. 慎把“DataContext”静态化 或则单例

    之前在项目里由于把DataContext静态化,最后在测试阶段发现了很多奇怪的问题,后来经过同事的指点 然后上网搜了一翻终于发现 MSDN上说:   "请不要试图重用 DataContext ...

随机推荐

  1. 【app】自动化必备之adb使用

    1.1 Adb介绍 adb(android debug bridge)是android sdk自带的一个工具 Adb是用来连接android设备和PC端的桥梁,通过adb工具,用户可以在PC端对手机进 ...

  2. 解决Python中PyCharm导入模块时,模块名下出现红色波浪线的问题

    在博主第一次在PyCharm中导入模块时,模块名下出现红色波浪线,不影响程序执行,但强迫症忍不了 以下是解决办法 Let's do it ... 进入设置,找到Console下的Python Cons ...

  3. 最优路径算法合集(附python源码)(原创)

    主要的最优(最短)路径算法: 一.深度优先算法:二.广度优先算法:三.Dijstra最短路径:四.floyd最短路径(待): 一.深度优先算法 图的深度优先搜索(Depth First Search) ...

  4. 微信小程序入门(三)

    11.开发框架基本介绍 四个组成部分,其它三个前面介绍过了,主要WXS: WXS:对wxml增强的一种脚本语言,可以对请求的数据进行filter或者做计算处理,帮助wxml快速构建出页面结构. 12. ...

  5. VueJs(1)---快速上手VueJs

    [VueJs入门] 版权声明 首先申明:此篇博客不是本人原创,只是最近开始学习vue.jS,看到有作者写的很不错,我仅在它的基础上仅仅是修改了样式 原文博客地址:https://blog.csdn.n ...

  6. Linux编程 17 文件权限(权限设置chmod,改变文件属主属组关系chown,chgrp)

    一. 概述 如果创建了一个目录或文件,有时会需要改变它的安全性设置,在linux系统上有一些工具可以完成这任务,包括使用chmod命令改变已有默认权限,分别能对属主,属组,其它用户的权限的控制分别以读 ...

  7. sql server 备份与恢复系列二 事务日志概述

    1.1  日志文件与数据文件一致性 在上一章备份与恢复里了解到事务日志的重要性,这篇重点来了解事务日志. 事务日志记录了数据库所有的改变,能恢复该数据库到改变之前的任意状态.在sql server实例 ...

  8. Elasticsearch实践(一):基础入门

    本文以 Elasticsearch 6.2.4为例. 注:最新(截止到2018-09-23)的 Elasticsearch 是 6.4.1.5.x系列和6.x系列虽然有些区别,但基本用法是一样的. 官 ...

  9. for循环输出素数探究【java】

    一.判断953是不是为素数(质数). 代码: /** 判断953是不是为素数(质数) 分析: 素数指整数在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数. 假设953是素数,则: ...

  10. web进修之—Hibernate 懒加载(6)

    关于懒加载 在关系数据库设计的时候,我们很多时候把表之间的关系设置为强关联(使用外键进行约束),在Hibernate中利用对象的包含关系进行维护(HIbernate本身就是面向对象的数据库操作模式), ...