https://kotlinlang.org logo
#android
Title
# android
c

ClaudiuB

11/09/2018, 5:49 AM
When should I use
context!!
versus
context?
in my Fragments? I'm thinking using
context!!
in my lifecycle methods and
context?.let{}
where I get callbacks
g

gildor

11/09/2018, 5:51 AM
Depends on your use case
Also I use
requireContext()
to get non-nullable context
c

ClaudiuB

11/09/2018, 5:52 AM
Can you elaborate a bit?
For non-UI logic i already use an application context provided by DI, so I don't really have issues on that layer
g

gildor

11/09/2018, 5:54 AM
sure, but if you want Activity context on Fragment you have 2 choices: use getContext() for nullable context or requireContext() to crash if context is null
d

dvlwj

11/09/2018, 6:04 AM
isn't
!!
make the app crash when there is some error? i think its not wise for app that alr launch
g

gildor

11/09/2018, 6:05 AM
But sometimes you want to crash if somebody call method in a wrong way, wrong lifecycle phase and so on
as I said, it depends on case
if it’s just some non-important operation, you can use
?
and just do nothing if contetxt is null, sometimes you need context
c

Christian Maier

11/09/2018, 6:17 AM
I'd recommend to never use double-bang
r

rnpy

11/09/2018, 6:22 AM
depends on the case tbh, sometimes it can make sense to just use
!!
instead of adding convoluted checks imho, as long as the stacktrace in case of a crash is clear enough (especially when working on legacy code)
c

Christian Maier

11/09/2018, 6:32 AM
Luckily until today I was always able to get rid of it
I'd like to see it as "hey, this is me probably shooting myself and yes, I'm completely fine with it."
g

gildor

11/09/2018, 6:34 AM
!!
instead of adding convoluted checks imho
I prefer methods like requireContext (in this case) or something like getOrThrow() instead of
!!
👍 1
👌 1
d

dvlwj

11/09/2018, 7:31 AM
hmm interesting discussion
c

ClaudiuB

11/09/2018, 8:26 AM
Then I guess it is a question of when can you use
requireContext()
. Is it valid to only use it in lifecycle methods (
onAttach() -> onDestroy
) ?
r

rnpy

11/09/2018, 8:30 AM
also on user action I'd say, on a click listener for example it makes sense to assume the context is not null
c

ClaudiuB

11/09/2018, 8:35 AM
That also makes sense. Do we know when
context
starts being null? Like precisely after a lifecycle method?
r

rnpy

11/09/2018, 8:45 AM
pretty sure it's null before
onAttach
/ after
onDetach
g

gildor

11/10/2018, 9:57 AM
also on user action I'd say, on a click listener for example it makes sense to assume the context is not null
Actually this is not always true, click is also asyncronous action managed by looper's event loop and in some cases you can get call backs after fragment detach
👍 2
i

igor.wojda

11/10/2018, 11:38 AM
c

ClaudiuB

11/10/2018, 12:15 PM
Related to that, should references to views be nullable or non nullable in fragments? The article said you could use
val recyclerView: RecyclerView by bindView(R.id.recycler)
which ended up being non nullable. Is that safe?
I use databinding and
binding?. let {}
a lot in callbacks. Is there a way to check if we can do operations on our views?
i

igor.wojda

11/10/2018, 4:19 PM
I am not familiar with data binding, so my answer may not be complete, but regarding views it depends. In above example where you retrieve view by Id - I would keep them non-nullable as usually when the view is there you messed something up and we want to follow fail-fast practice. However there may be a scenario where on activity have more than one layout for different device configuration (eg. phone vs tablet or vertical vs horizontal). There layout may differs in child views (eg. Tablet cna display more data, so there may be some extra view). If you are aware of this fact then you can make a view nullable, because it exists only in some of the layouts. Regarding Presenters from MVP nullable/non-nullable type of the view it’s an architectural decision, but just to be safe I would keep them nullable. Regarding context usually we can use application context for things like
startActivity
. You can easily obtain it from custom application class (configured in AndroidManifest) and assume it will be initialises latter and always be non-nullable (utilising
lateinit
modifier)
Copy code
class MyApplication : Application() {
    lateinit var context: Context
    
    override fun onCreate() {
        super.onCreate()

        this.context = context
    }
}
Then you can just staticky access it (not so nice) or inject it into Activity (proper way of doing things)
t

tateisu

11/10/2018, 5:18 PM
in some device/situation Application.onCreate is not called before initializing of Activity/Service/Receiver. you may know it when reading crash report in real world. the work around is call something static method in companon object in each onCreate on Activity/Service/Receiver/etc.
r

rnpy

11/10/2018, 11:45 PM
val recyclerView: RecyclerView by bindView(R.id.recycler)
is not safe, it you try to access it before onViewCreated for example (or after view destroyed) it will throw an NPE, so technically using
RecyclerView
instead of
RecyclerView?
can be considered wrong. But it all depends on where you decide to draw the line for "too many checks", and what you want to do when one of these fail (in some cases you can just ignore what happened if the view is gone, but in others you could want to consider it an error)
using the application context is often wrong though 🤔
c

ClaudiuB

11/12/2018, 5:03 AM
why is using the application context often wrong?
As long as you don't pass that to views, I thought that's fine
g

gildor

11/12/2018, 5:13 AM
Application context is fine, but you cannot use to start a new activity on the same task, show dialog and for some other things
r

rnpy

11/12/2018, 8:57 AM
there's a reason you get a local and app context, they're not the same thing, resources you get from them can be different for example, especially in multi-window / split view, themes are also different, basically anything UI related should always use local context, or you can be in for some nightmarish debugging
also I've seen it used with things like Glide for loading images, that's also pretty awful and can easily lead to leaks, since it won't link loading to the right context. Glide links loading to the context lifecycle to cancel calls/reuse bitmaps, most of the time it will still be freed using app context, but not in all cases (again, nightmarish debugging, but even a step above previous one)
6 Views