作者:Antonio Leiva

时间:Mar 9, 2017

原文链接:https://antonioleiva.com/property-delegation-kotlin/

如我们在前面文章中读到的,属性需要默认值,不能声明属性,而不给它们赋值。

由于你要存储视图到属性中,这就产生一个问题了。在对象创建期间,这赋值代码将被执行,而此时你不能访问这个内容。

那你有能做什么?

属性委托:委托属性值到另一个对象

属性委托将使用另一个对象,这个对象能够调用get和set(如果使用了var)返回结果。

目前,我们还不能控制许多对象的创建,如Android框架,在许多情况下,这委托将挽救我们的生命。

我将向你展示三个例子,我认为它们在Android中非常有用。

设置视图到属性

对于这个例子,我们用委托有两个选项,且禁止用null(如果你能够避免它,有些事情不建议使用)。

这是我最喜欢的,因为它迫使你对于不可变的、不太安全的属性使用var。

用保留字lateinit,说明属性不能为空,但是我们仍然没有final价值:

 lateinit var textView:TextView

在onCreate,我们能够赋值给final值:

 setContentView(R.layout.activity_main)
textView = findView(R.id.welcomeMessage)
toast(textView.text)

尽管它与委托notNull做相同的操作、被归入第一喜欢,但这不是真正的委托。

第二个选择则更加优雅。它由Lazy委托组成,直至属性第一次被调用,相关代码是不会执行:

 val textView by lazy { findView(R.id.welcomeMessage) }

在textView的get被第一次调用之前,findView是不能运行的。由于你不能错误的修改其值所以它更安全,并且它不会强制我们在setContentView之后记得设置它。

此刻,我们做:

 toast(textView.text)

这行代码将在lazy形式下被执行。

如你所见,委托的方式用by保留字表示。

我们来看另一个例子。

通知适配器变更

在适配器中,我们有items属性,每次自动启动adapter时更新。

 var items: List by Delegates.observable(emptyList()) {
_, _, _ -> notifyDataSetChanged()
}

它简单地设置初始值,然后在每次更改后调用定义的函数。

在这种情况下,我只是调用notifyDataSetChanged,但是,如你所见,函数收到的新旧两个值,所以在技术上你可以检查变化是什么,只更新其区别。

如果你对这个例子有兴趣,我在另一篇文章更广泛的描述它

声明Lazy方法的Dagger图

这是我发现的非常有用的另一个情形。

返回到lazy,你能够在属性声明期间,用它声明应用的component:

 val component: AppComponent by lazy {
DaggerAppComponent
.builder()
.appModule(AppModule(this))
.build()
}

这个方法,你不需要用lateinit,属性则为不可变的。

如果在Activity中,用subcomponents,你能够做相同的事:

 class HomeActivity : AppCompatActivity(), HomePresenter.View {
val component by lazy { app.component.plus(HomeModule(this)) }
...
}

新Kotlin 1.1版本:局部委托属性

我们已经见到怎样用委托是给我们类属性的额外能力。而例如lazy,对变量也真的有帮助吗?Kotlin是缺乏这一特性的。

现在,用局部委托属性,我们做:

 fun testLocalDelegation() {
val database by lazy { createDatabase() }
val cache by lazy { createMemoryCache() } if (mustUseDatabase()) {
database.use { ... }
} else {
cache.use { ... }
}
}

尽管不使用lazy委托,这个例子能够解决,但它还是有助于理解这些概念。

我们有几个可能会或不会被使用的“笨重”对象。通过用lazy,我们能够推迟它们的实例化,直到我们确信要使用它们

在首次使用时,花括号内的代码被执行,且被缓存起来,以备以后再使用。

结论

属性委托将帮助你属性更强大,更简化,且代码可重用。

这里我们仅仅看到Kotlin库的标准属性,而你能够创建你自己的属性

例如在这本书中,我有实现从SharedPreference存储和取回数据。

如果你要学习更多这些内容,足够流畅创建自己的Android应用程序,我建议你获取这本免费指南,学习怎样创建你的第一个项目,或直接获取这本书,学习怎样从头开始创建一个完整的应用程序。

Kotlin的属性委托:无上下文情况下Android的赋值(KAD 15)的更多相关文章

  1. UIView的clipsToBounds属性,layoutSubViews及触摸事件传递(默认情况下)总结

    一.UIView的clipsToBounds属性 * 默认情况下,超出父控件尺寸范围的子控件还是可见的 * 如果设置父控件的clipsToBounds=YES,就会裁剪掉超出父控件尺寸范围内的子控件, ...

  2. css考核点整理(八)-在什么情况下通过img引入图片,什么情况用背景图引入?背景属性有哪些

    在什么情况下通过img引入图片,什么情况用背景图引入?背景属性有哪些

  3. 同一容器中a标签比较多的情况下通过title属性值隐藏

    同一容器中a标签比较多的情况下如何通过title属性值控制a标签的隐藏或显示 最近项目中遇到一个IE兼容性问题,网站需要在底部footer添加"站长统计"代码,容器中动态添加很多a ...

  4. 在启用属性的情况下启动 Confluence 6

    在一些情况下,你可以希望 Confluence 在系统启动的时候就对属性文件进行打印.如果你的 Confluence 经常进行重启,并且你可能忘记来启动针对系统诊断的属性文件日志开关. 编辑 CONF ...

  5. ConnectionString属性(网速慢的情况下研究Connect Timeout)

    ConnectionString 类似于 OLE DB 连接字符串,但并不相同.与 OLE DB 或 ADO 不同,如果“Persist Security Info”值设置为 false(默认值),则 ...

  6. Kotlin属性委托系统总结与提供委托详解

    属性委托总结回顾: 在前三次已经将Kotlin委托相关的知识点进行了完整的学习了,具体博文如下: https://www.cnblogs.com/webor2006/p/11369019.html h ...

  7. Kotlin代理属性--官方文档翻译

    代理属性 Delegated Properties 本文为个人翻译的Kotlin官方文档, 原文连接: Delegated Properties 一些特定的常见类型的属性, 尽管我们可以在每次需要的时 ...

  8. 如何设置iframe高度自适应,在跨域的情况下能做到吗?

    在页面上使用iframe来动态加载页面内容是网页开发中比较常见的方法.在父页面中给定一个不带滚动条的iframe,然后对属性src指定一个可加载的页面,这样当父页面被访问的时候,子页面可以被自动加载. ...

  9. KVM虚拟机内无agent情况下的监控方法

    KVM虚拟机内无agent情况下的监控(ceilometer实现) 今天看到大家在群里讨论KVM虚拟机的监控问题,而且是要求VM内无agent情况下的监控.这方面确实没有深入研究,但尚有些openst ...

随机推荐

  1. 【翻译】苹果官网的命名规范之 Code Naming Basics-General Principles

    苹果官方原文链接:General Principles 代码命名基本原则:通用规范   代码含义清晰 尽可能将代码写的简洁并且明白是最好的,不过代码清晰度不应该因为过度的简洁而受到影响.例如: 代码 ...

  2. 学习换脸:Switching Eds: Face swapping with Python, dlib, and OpenCV

    学习GitHub上比较火换脸博客,原英文版:https://matthewearl.github.io/2015/07/28/switching-eds-with-python/ 系统win10,x6 ...

  3. code First 三 Fluent API

    Entity Framework Fluent API用于配置域类以覆盖约定. 在实体框架6中,DbModelBuilder类充当Fluent API,我们可以使用它来配置许多不同的东西.它提供了比数 ...

  4. 你不知道的javaScript笔记(1)

    规避冲突 function foo(){ function bar(a){ i = 3; console.log(a + i); } for ( var i=0; i < 10; i++){ b ...

  5. 没有上司的舞会(树形DP)

    题目描述 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司.现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数Ri, ...

  6. 《Linux 性能优化实战—倪朋飞 》学习笔记 CPU 篇

    平均负载 指单位时间内,系统处于可运行状态和不可中断状态的平均进程数,即平均活跃进程数 可运行状态:正在使用CPU或者正在等待CPU 的进程,也就是我们常用 ps 命令看到的,处于 R 状态 (Run ...

  7. thinkphp5数据库导入Excel表格

    $data=$order_info; //$data 你要下载谁 就去查谁 // $data= Db::name('order_info') // ->field('consignee,tel, ...

  8. 【Laravel】查询构造器---使用orWhere的顺序对查询结果产生的不良影响

    实现查询:获取模糊匹配中文名 || 英文名等于 “Sara” 并且 个人信息状态为“待审核” 的员工信息. 其中 $filter = ["eName" => "Sa ...

  9. YII2 多MongoDB配置和使用

    1:在config/web.php 文件下配置多个连接即可: 注意在componets 下 'mongodb' => [ 'class' => '\yii\mongodb\Connecti ...

  10. scala成长之路(1)基本语法和数据类型

    scala作为JVM上的Lisp,是一种geek类型的编程语言,也一直是我等java程序员眼中的梦寐以求的一门技能,遂下定决心花一段时间好好学习scala.第一天学习,主要介绍与java在编程上的主要 ...