请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

在activity中使用代理,空指针怎么解决

在activity中怎么使用类似下面的代理
view中可以这么使用代理

view中可以通过init {View.inflate(content…)} 提前到 代理定以避免空指针,但是activity中要通过init{…}这种提前方案,好像找不到类似View.inflate类似的方法,我们在activity中都是通过在函数onCreate中去设置页面布局的,求老师解答

正在回答

3回答

bennyhuo 2020-04-04 20:52:14
activity init的时候 view还没有设置,你得等到setcontentview之后才行。activity的逻辑都要写在create之后,不要自定义他的构造器。
0 回复 有任何疑惑可以回复我~
  • 提问者 ak_star #1
    试了下还是空指针,我的代码如下:
    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)
    }
    回复 有任何疑惑可以回复我~ 2020-04-04 21:16:38
  • bennyhuo 回复 提问者 ak_star #2
    哦,我明白你的意思了。你是说下面的 label 定义时会抛异常了吧。因为 label 的代理初始化时在 Activity 构造阶段执行的,这个时候会去访问 hello 这个合成的属性,而 hello 本质上就是 findViewById,因此这时一定是空指针的。这里的根本原因是对于 hello 的访问不能在 onCreate 之前,所以不要这么写。
    
    如果一定要这个代理,可以定义一个内部类,例如 ViewHolder,把 label 放到 ViewHolder 当中,然后再类似这样写:
    
    val holder by lazy {  ViewHolder(contentView) } 
    
    同学可以试试。
    回复 有任何疑惑可以回复我~ 2020-04-04 21:34:05
  • 提问者 ak_star 回复 bennyhuo #3
    谢谢老师,内部类方案可以,代码如下
    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)
        }
    }
    回复 有任何疑惑可以回复我~ 2020-04-04 21:58:48
bennyhuo 2020-04-06 08:30:48
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" 
    }
}


1 回复 有任何疑惑可以回复我~
提问者 ak_star 2020-04-04 23:18:46

经过老师的提点,对lazy源码又看了一遍,写出一个var 版本的lazy来做到懒加载初始化 Lambda表达式的内容。代码如下:

https://img1.sycdn.imooc.com//szimg/5e88a520098ac52309920847.jpg

private var lazyLabel by lazyDelegate { delegateOf(hello::getText, hello::setText) }

1 回复 有任何疑惑可以回复我~
  • 想法不错~不过你这样 lazyLabel 就成了 ReadWriteProperty 的类型了,本意应该是想要让它的类型为 String 吧。
    回复 有任何疑惑可以回复我~ 2020-04-05 09:32:28
  • 可以稍微改下,让 lazyDelegate 的 get 和 set 里面直接调用下内部的 delegate 应该就可以了。
    回复 有任何疑惑可以回复我~ 2020-04-05 09:35:26
  • 你倒是提醒了我可以把这个框架改下,支持传入函数以支持懒初始化。
    回复 有任何疑惑可以回复我~ 2020-04-05 09:37:27
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信