Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kotlin下init调用setContentView会有构造参数未初始化的问题 #478

Open
nemo-ex opened this issue Oct 18, 2022 · 5 comments
Open

Comments

@nemo-ex
Copy link

nemo-ex commented Oct 18, 2022

提issue前请去WIKI#常见问题查询相关问题,避免重复提问

Please go to WIKI#FAQ for relevant questions before commit your issue to avoid repetitive questions.


提issue前请务必参考以下格式填写,否则该问题会被直接关闭。

Please be sure to follow the format below before submitting the issue, otherwise the question will be actively closed!

  • 系统版本(必须)/ Any:
  • 库版本(必须)/ 3.0+:
  • 问题代码/截图(可选)/ Problem code or screenshot (optional):
  • 报错信息(可选)/ Error reporting information (optional):

问题描述/重现步骤请写在这里
Please write the description here.

kotlin下init调用setContentView会有构造参数未初始化的问题

class TestPopupWindow(context: Context, private val data: String) : BasePopupWindow(context) {

    init {
        // init在构造函数赋值前执行,这个时候类上的构造参数未初始化
        contentView = createPopupById(R.layout.test_popup)
    }

    override fun onViewCreated(contentView: View) {
        super.onViewCreated(contentView)
        println("data: $data") // 这里打印null
    }
}

可以改成constructor()使用,但是这样写起来就比较麻烦,变量要定义在外面,而且idea有黄色提示

class TestPopupWindow : BasePopupWindow {

    private val data: String

    constructor(context: Context, data: String): super(context) {
        this.data = data
        contentView = createPopupById(R.layout.test_popup)
    }

    override fun onViewCreated(contentView: View) {
        super.onViewCreated(contentView)
        println("data: $data") // 这里打印正常
    }
}

image

还有什么比较好的解决方式吗?

@nemo-ex
Copy link
Author

nemo-ex commented Oct 18, 2022

是否可以考虑在BasePopupWindow构造函数中增加一个类似老版本的onCreateContentView回调方法,没有返回值,只是用于告诉子类父构造初始化完成了,子类再覆写这个方法去setContentView
@razerdp

@razerdp
Copy link
Owner

razerdp commented Oct 18, 2022

我记得你的data写到init外部也会当成主构造函数一部分吧?

class(xx){
var data = xx
init{}
}

@nemo-ex
Copy link
Author

nemo-ex commented Oct 18, 2022

是否可以考虑在BasePopupWindow构造函数中增加一个类似老版本的onCreateContentView回调方法,没有返回值,只是用于告诉子类父构造初始化完成了,子类再覆写这个方法去setContentView @razerdp

搞错了,测试不行

fun main() {
    Child("Joe")
    // 输出:
    // Father constructor Joe
    // Child call null
}

open class Father {
    constructor(data: String) {
        println("Father constructor $data")
        childCall()
    }
    open fun childCall() {}
}

class Child(val data: String) : Father(data) {
    override fun childCall() {
        println("Child call $data")
    }
}

@razerdp
Copy link
Owner

razerdp commented Dec 28, 2022

在constructor中call子类的方法,子类是无法访问的,因为java的加载问题,此时其实仍然在父类的加载过程中,子类的变量还没赋值,是初始值null

@razerdp
Copy link
Owner

razerdp commented Dec 28, 2022

这也是为啥我抛弃了之前lazypopupwindow的原因,只有走到的init时,才开始对子类变量赋值,此时setcontentview才有效

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants