Is getting references to views in an Activity like...
# android
g
Is getting references to views in an Activity like this considered a bad practice ?
Copy code
val button : Button by lazy {
    findViewById(R.id.button)
}
r
Well if you put that code inside an Activity directly, then yes, it’s very bad.
s
I've had issues with this in the past with navigating back to fragments, at least. Remember that the fragment/activity might be destroyed while the actual object might still exist.
👍 1
g
@ribesg why do you think so? @sindrenm what do you mean with "the actual object?" the fragment/activity? or the view? or the lazy?
r
Well inside a
Fragment
it’s wrong, but inside an
Activity
it may be ok
g
@ribesg what's the reason
r
Look at the Fragment lifecycle

https://developer.android.com/images/fragment_lifecycle.png

See how the view can be destroyed then re-created in the same Fragment instance. You then have (in your case) a reference to a Button that is no longer attached to anything, and which is NOT the Button displayed on screen.
👍 3
g
maybe just easier to use synthetics and not bother with onCreateView or only use onCreateView to inflate your fragment and use synthetics in onViewCreated
👍 1
s
I use synthetic imports myself and haven't had problems with them. Although I tend to also keep references to them in the activity/fragment as well, but through “virtual” properties with a getter:
Copy code
private val button: Button
  get() = the_button_in_the_layout // synthetically imported
g
@ribesg Makes sense, thanks 👍
What if I was to keep a reference to the whole View like so
Copy code
private val rootView : View by lazy { inflateView() }

override fun onCreateView(): View{
    return rootView
}
Would this be bad practice ?
r
Or just don’t use XML views 😛
@gsala don’t start to work around the android lifecycle, it’s a very dark path. Just deal with it
g
I'm not doing any of these things. But I needed to understand the reason behind why it's not a good idea
r
You can safely do that
Copy code
val button : Button
    get() = findViewById(R.id.button)
But in this case you may end up calling
button
multiple times in the same function like it’s nothing. Well, it’s not huge, but it’s better to have a local var and call
findViewById
only once if you can
g
KotterKnife (https://github.com/JakeWharton/kotterknife/blob/master/src/main/kotlin/kotterknife/ButterKnife.kt) appears to be implemented like the first case though
r
That’s not what I’m understanding from the link you give
g
🤔 How do you understand the implementation then?
s
@ribesg: Note that I was using a getter together with synthetic imports, which does in fact cache the views for you. Just so there's no misunderstanding. simple smile
r
@sindrenm Yes, it would be best but if you have synthetic imports you just use them directly usually
@gsala I don’t know, I don’t see anything returning a lazy val. Wait I’m not sure I read this code correctly
s
Yeah, but some people use snake_case in IDs and some people use prefixes (e.g.
signInEmailAddressEditText
), so I prefer to keep track of them in property getters. simple smile
r
@gsala oh, I see. Nothing tells you to bind your views as property though. The given example is inside a ViewGroup
g
True. I'm now reading through the conversation that spawned this reply : https://kotlinlang.slack.com/archives/C0B8M7BUY/p1532693549000239
r
In ButterKnife, you should call
ButterKnife.bind(this);
after the view has been created to replace the instances by the ones for the newly created view, which dereferences old views in the process
s
Indeed, but that thread is so 2018. 😏
r
For me the best way is not to have XML anyway
Just have your views with direct references to what you need. Anko was great for that, now you should use Splitties View DSL instead
s
Yeah, Anko was great for that and Splitties probably is, but I'm just so incredibly used to the preview thingymabob that I've grown quite dependent on it. Although I don't seem to need it when writing Flutter apps (a whole discussion all in its own, I guess), but then again that has proper hot reloading. 😛
r
Both Anko and Splitties support preview in IDE
I don’t use it much, as when you write Kotlin code you just know what it will look like, but it works. You can’t build your view graphically, which is a good thing because usually the graphical editor writes things you don’t want/need
s
Yah, they do support it, but you'll have to build the code first, which is not the case for XML layouts. And while I usually know what I want, it's a whole lot easier to be able to preview my constraint layouts while writing it. And no, I don't build my layouts graphically, I prefer having full control over the resulting XML. Although, to be fair, the WYSIWYG editor does usually build decent XML.
r
It’s not like writing views with code is long, compared to XML
You start with something like
Copy code
class MainView(override val ctx: Context) : Ui {

    override val root = constraintLayout ()

}
s
Oh, I know it's not long. I really like the idea behind it. And I did use Anko UI for a while. But complex views are a bit … complex.
But I feel like we digress from the original question. Let's leave it at that. 😛
r
Copy code
class MainView(override val ctx: Context) : Ui {

    val myTextView =
        textView {
            textResource = R.string.my_string
        }

    override val root = constraintLayout {

        add(myTextView, lParams {
            centerInParent()
        })

    }

}
Splitties is better than Anko, it works differently and fixes some general issues. And for complex views, you can very easily split them in multiple files. It’s also a lot better to just have your views there, like
myTextView
in my example. It’s just there. In my Activity/Fragment I just have
view.myTextView
. Also parsing XML is something not-trivial in terms of resources 😛
s
As I said, I really like the concept, no need to convince me. Like, I love having stuff like
centerInParent()
, for instance. But the preview is not as good as it is with XML layouts. Also, the XML files aren't shipped as XML, it's binary. simple smile
r
Was talking about the preview 😛
s
Oh, right. Yeah, that's definitely not for free. 😛
z
If you can, you should most likely disable thread safety over this, it's not like you need double-check lock synchronization to get a view from your view's... views. Lately it is easier to just use Kotlin synthetics
👍 2
l
I'm also a big fan of Kotlin synthetics
r
Bigger fan of databinding 😔
l
Came back to this 3 months later, looks like kotlin synthetics are not very performance friendly! Need to learn databinding asap. Also just found kotterknife, wondering how that will be
r
Better off learning databinding