DylanCaiCoding/ViewBindingKTX

FragmentBindingDelegate 这个委托类中使用后备属性(支持属性技术)shifou

Closed this issue · 2 comments

image

下划线后备属性本意是为了
延迟初始化。但是这里by委托类
getValue本身就近似达到了延迟初始化的要求

且binding的get()方法并无特殊功用,没有体现后备属性的用法,

看起来使用后备属性仅仅是不想多写!!而已

看我的图。我实在不知道不知道为什么会多写两行,虽然对 后备属性私有访问,编译器是可以不调用getter方法,无函数调用损耗,但是多写这个我认为无用的代码,我实在看着别扭,往大佬打脸指教下。

为了这个细小问题,我搜索看了好多文章对于后备字段,后备属性,支持属性,延迟初始化,惰性初始化的讲解,最后汇总还是感觉图上的委托类,getvalue方法中对后备属性的使用时多余的很,这个问题我在 很多地方见到过,比如

张鸿阳 kotlin-android-extensions 插件也被废弃了?扶我起来 一文中
image
对viewbing在fragment中的初始化也是用的后备属性,我对此写法的看法是优点在于后面在使用viewbing字段的时候不用每次都写!!毕竟fragment中对viewbing的调用可能有很多次,省下!!也是值得的,

所以大佬你的委托类不对外开放,却使用了后备属性节约了一点点 对!!的书写,实在感觉怪怪的。

这个问题困扰我好久了,大佬抽出时间解答探讨下,就不胜感激了!!

总结了下有两个问题:

  1. 为什么属性委托使用了 _binding 和 binding?

当时是出于代码可读性的考虑,保留了这两个变量。如果用过官方的 Fragment 用法,读属性委托源码会更容易理解,刚开始初始化 _binding,然后获取 binding 来使用,onDestroyView 时销毁 _binding。可以理解为,那一行的委托代码:

val binding : FragmentHomeBinding by binding()

能等效于 FragmentBindingDelegate 内部的 _binding 和 binding,这样看源码会比较容易理解,因为 Fragment 就是这么来用的。

var _binding: VB? = null
val binding: VB? get() = _binding!!

我最开始就是你图中的写法,后面纠结了很久才把 _binding 加上,虽然我是希望用尽可能少的代码实现功能,但是多一行代码能让代码更容易理解,也不是不能接受。然而这给你学习属性委托造成了困惑,是我万万没想到的,我可能要重新考虑一下。

  1. 为什么 Fragment 不用 laterinit 初始化 binding?

因为 laterinit 的不能是可空的类型,而 Fragment 需要在 onDestroyView 置空,所以定义的类型需要是 VB?,这就不能使用 laterinit。

这又引出个问题,为什么在 Fragment 使用要置空?个人目前的理解是 onDestroyView 把视图销毁了,但是 binding 对象还持有着视图,所以这个被释放的 View 在 onDestroyView 后还存在内存中并未及时的释放,这是不合理的。不知道还有没有其它隐患,反正在 onDestroy 释放了总没错,官方也是这么要求的。

委托类的代码已修改提交了,生命周期代码也做了点修改,兜兜转转还是回到了早期写的版本。阅读代理模式的代码个人会用等效替换的方式去理逻辑,可能别人并不是这么来思考。所以现在回头想了下,这么来写感觉并不是很合适。