kotlin-学习-语法3-Built-in delegates
词汇
by :关键字 指定类委托 、属性委托
lazy():是一个函数, 接受一个 Lambda 表达式作为参数, 返回一个 Lazy 实例的函数,返回的实例可以作为实现延迟属性的委托: 第一次调用 get() 会执行已传递给 lazy() 的 lamda 表达式并记录结果, 后续调用 get() 只是返回记录的结果。
Delegates.observable(): 函数接受两个参数: 第一个是初始化值, 第二个是属性值变化事件的响应器(handler);在属性赋值后会执行事件的响应器(handler),它有三个参数:被赋值的属性、旧值和新值
notNull: 适用于那些无法在初始化阶段就确定属性值的场合。需要注意,如果属性在赋值前就被访问的话则会抛出异常
Delegates.vetoable(): 变量值更新前的拦截,可以控制是否接收改变
文章
视频
android Developer订阅号-Built-in delegates - Kotlin Vocabulary
android Developer订阅号-Delegating delegates - Kotlin Vocabulary
Delegates help you delegate tasks to other objects and provide better coder use,which you can learn more in this video.
Kotlin not only supports an easier way to implement delegates with by[关键字 ] keyword, but also providers built-in delegates such as lazy,observable ,vetoable,and not null in the kotlin standard library.
Let's see these built-in delegates and how they work under the hood. But,before that ,I bet you'll like this video and want to subcribe to the channel. Don't you .
lazy()
The lazy function is a property delegate that helps you to lazily initialize properties.
That's when they are first accessed .Lazy can be really helpful for objects which are expensive to create.
image.pngLazy takes two parameters ,a LazyThreadSafetyMode enum value and a lambda.
The lazyThreadSafetyMode parameter specifies how the initialization is synchronized between different threads. Lazy uses a default value of LazyThreadSafety Mode.SYNCHRONIZED,which means the initialization is thread safe at the cost of a slight performance impact from explicit synchronization.
lazy(){
// initializer
}
The lambda is executed when the property is accessed for the first time. And its value is stored for future access.
image.pngWhen checking the decompiled Jave code, we seee that the Kotlin comipler creates a reference of object type lazy for the lazy delegate.
image.pngLet's take a took at the source code of lazy function. Since the lazy function uses LazyThreadSafetyMode synchronized by default,it returns a lazy object of type synchronized lazy input class.
image.pngWhen teh delegated property is first accessed the getvalue function of SynchronizedLazyImpl is called ,which initializes the property in a synchronized block.
This guarantees that the lazy object is initialized in a thread safe manner ,but it's the performance cost of the synchronized block.
If you are sure that this resource will be initialized by a single thread ,you can pass LazyThreadSafeMode.NONE to lazy and the function will not use the synchronized block during initialzation.
However,keep in mind that LazyThreadSafetyMode.NONE doesn't change the synchronous nature of lazy initialization. Lazy initialization still takes the same amount of time as non-lazy initialization of the object on the first access.
This means objects which take long to initialize can still block the UI thread if accessed from it . Lazy initialization can be helpful to initialize expansive resources.
image.pngHowever ,for simple objects ,such as a string lazy adds overhead by generating other objects, such as lazy and KProperty.
Delegates.observable()
observable is another built-in delegate of the Kotlin standard library.
image.pngObserver is a design pattern in which an object maintians a list of its dependents called observers and notifies them automatically when its state changes.
image.pngThis pattern can be really helpful when more than one object needs to be informed wehn a value has changed,rather than having each dependent object periodically call and check if the resource is updated.
Observable takes two parameters--the initial value and the listener handler that will be called when the value is modified. Observable creates an observable property object that executes the lambda you pass to the delegate each time the setter is called.
image.pngLooking ta the decompiled person class, we see that the kotlin compiler generates a class that extends the observable property. This class also implements a function called afterChange that has the lambda function ,which is passed to the observable delegate.
image.pngThe afterChange function is envoked by the setter of the parent observable property class. This means each time a caller sets a new value for address, the setter will automatically mark the afterChange function,resulting in all the listeners to be nofitied about the change.
You can also see a call to beforeChange in the decompiled code. beforeChange is not used by the observable delegate, but is used by the delegate which is coming up next. Vetoable
Delegates.vetoable()
image.png
Vetoable is another build-in delegate in which the property delegates veto rights to its value. Similar to the observable delegate, vetoable takes two parameters--the initial value and the listener handler that will be called wehn any caller wants to modify the value of the property.
image.pngIf the lambda function returns true, the property value will be modified. Else ,the value will stay the same. In this case, if the caller tries to update the address with anything smaller than 15 characters, the current value will be preserved.
image.pngLooking at the decompiled person class, Kotlin generates a new class ,which extends to observable property . The generated class includes the lambda we passed in beforeChange function,which will be called by the setter before the values is set.
Delegates.notNull()
The last built-in delegate I'll talk about is Delegates.notNull. notNull simply allows the property to be initialized at a later time.
image.pngnotNull is similar to lateinit. In most cases,lateinit is preferred, since notNull creates an extra object for each property. However,you can use notNull with primitive types, which lateinit doesn't support.
image.pngwhich lateinit doesn't support. notNull uses a special type of read-write property named notNull var.
image.pngLooking at the decompiled code ,the full name property is initialized with the notNull function,which returns a notNull var object.
image.pngThe notNull var class simply holds a generic nullable internal reference and throws illegal state exception if any call calls the getter before the value is initialized.
The kotlin standard library provides a set of built-in delegates so you don't need to write ,maintain, and reinvent them.
Built-in delegates initialize fields lazily,allow primitive types to be initialized later, observe and get notified when a value changes , and even veto those changes.
Thanks for watching.