采纳答案成功!
向帮助你的同学说点啥吧!感谢那些助人为乐的人
在activity中怎么使用类似下面的代理
view中可以通过init {View.inflate(content…)} 提前到 代理定以避免空指针,但是activity中要通过init{…}这种提前方案,好像找不到类似View.inflate类似的方法,我们在activity中都是通过在函数onCreate中去设置页面布局的,求老师解答
试了下还是空指针,我的代码如下: class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } // hello 为xml中定义的一个TextView var label by delegateOf(hello::getText, hello::setText) }
哦,我明白你的意思了。你是说下面的 label 定义时会抛异常了吧。因为 label 的代理初始化时在 Activity 构造阶段执行的,这个时候会去访问 hello 这个合成的属性,而 hello 本质上就是 findViewById,因此这时一定是空指针的。这里的根本原因是对于 hello 的访问不能在 onCreate 之前,所以不要这么写。 如果一定要这个代理,可以定义一个内部类,例如 ViewHolder,把 label 放到 ViewHolder 当中,然后再类似这样写: val holder by lazy { ViewHolder(contentView) } 同学可以试试。
谢谢老师,内部类方案可以,代码如下 class MainActivity : AppCompatActivity() { private val holder by lazy { ViewHolder(hello) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) hello.setOnClickListener { holder.label = "你好" } } class ViewHolder(private val v: TextView) { var label by delegateOf(v::getText, v::setText) } }
private var text by delegateLazyOf(TextView::getText, TextView::setText) { textView }
看看这个感觉如何。我更新了一下这个组件, API 稍微有些调整,同学可以试试:
implementation("com.bennyhuo.kotlin:delegates:1.0")
同步到 jcenter 需要点儿时间,如果 jcenter 找不到,添加下面的仓库:
repositories { maven { url "https://dl.bintray.com/bennyhuo/bennyhuo" } }
经过老师的提点,对lazy源码又看了一遍,写出一个var 版本的lazy来做到懒加载初始化 Lambda表达式的内容。代码如下:
private var lazyLabel by lazyDelegate { delegateOf(hello::getText, hello::setText) }
想法不错~不过你这样 lazyLabel 就成了 ReadWriteProperty 的类型了,本意应该是想要让它的类型为 String 吧。
可以稍微改下,让 lazyDelegate 的 get 和 set 里面直接调用下内部的 delegate 应该就可以了。
你倒是提醒了我可以把这个框架改下,支持传入函数以支持懒初始化。
登录后可查看更多问答,登录/注册
Kotlin中文社区负责人亲授|Kotlin高级特性深层次解析与实践
603 1
837 12
721 10
918 9
715 9