The main problem I meet. ``` class MyView:View{ ...
# announcements
w
The main problem I meet.
Copy code
class MyView:View{
  private val myChildView:View = findViewById(R.id.my_view_id)
  init{
     View.inflate(R.layout.my_layout,this)
  }
}
There is a chance that myChildView is null because inflation is executed after findViewById.
l
It shouldn’t be a chance, it should always behave like this
w
Or I should say there is a chance that myChildView is not null.
d
You're letting
this
escape in the init block. that is usually a bad idea.
I can't reproduce this behavior with a minimal example though:
Copy code
fun main() {
    Foo()
}

fun getString() = "hello"

fun doWithString(s: String, foo: Foo) {
    println(s)
    println(foo.x)
}

class Foo {

    val x: String = getString()

    init {
        doWithString(x, this)
    }

}
prints "hello" twice correctly
l
@diesieben07 that’s the expected behaviour
d
Yes, I know.
Like I said in the other thread: The code runs in the order it is written in the source code.
w
I think it may because the complier reordering happens?
d
The compiler does not reorder things... What order are you seeing?
Are you saying in your case
findViewById
runs after
inflate
?
l
It actually can re-order things, in order to optimize them
d
Yes, but only if that doesn't change the observed behavior
w
In my case that can happens imo. View inflation is just parsing an xml file. it doesn’t know it will change the findViewById result or not.
d
what do you mean "can happen"... compilation either does one or the other ordering
its not ambiguous
w
🤔 because I have 2 build on the same phone with the same code. 1 crashes and the other now. That makes me confuse.
d
I am not too familiar with android, but can you decompile to java and check if the output is similar?
What crash d you see?
a
Isn’t this less of a case of order of execution, and more of a case of which functions you are using? There can be a case where the View is not actually inflated in the heirarchy, so findViewById will not find the referenced View.
l
From the code above there should be always a crash
findViewById
execute before inflating the view will return
null
d
The view ids are different, Luca
But I am really out of my water here with Android. So I'll 🤐
l
The
ids
are different because one is referencing a layout
Which contain a view with the
id
findViewById
is trying to find
if the
layout
is not inflated,
findViewById
will return
null
So, that code should always throw a
NPE
w
But in my case. The crash is not always happening. Interesting enough. I already ship the code in production and the un-crashed user is much higher than crashes. 😂
l
Can you check the decompiled code?
a
You could just find your child view after the inflation has happened.
Copy code
private lateinit var myChildView: View

init {
    View.inflate(R.layout.my_layout,this)
    myChildView = findViewById(R.id.my_view_id)
}
Or even lazily using
by lazy {}
l
@Alexander Johansson we're not searching for a solution 😂
w
There’s also an example in the docs (https://kotlinlang.org/docs/reference/classes.html): “During an instance initialization, the initializer blocks are executed in the same order as they appear in the class body, interleaved with the property initializers” So it shouldn’t be possible for your code to not crash 😕
Unless the base class does something that makes the
findViewById
not crash
l
Yep, that post confirmed what we were saying :)
Thanks for sharing though :)
w
Yep I just wanted to provide some sources. I expect OP’s snippet doesn’t show entire picture. For one it’s impossible to inflate a view into another View, so the base class must be
ViewGroup
for example
👍 1