Mar 2 | 8:50 AM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Mar 2 | 8:55 AM |
Vibhu | has entered the room |
Mark M. |
hello, Vibhu!
|
Mark M. |
how can I help you today?
|
Vibhu |
Hi Mark
|
Vibhu | |
Vibhu |
Is there any advice on best way to deal with that?
|
Mark M. |
I am not certain what you mean, sorry
|
Mark M. |
what exactly does "hygiene to handle static references to the app context" mean?
|
Vibhu |
Until now we had a static Context in our Application class
|
Mar 2 | 9:00 AM |
Mark M. |
the Application is a Context
|
Vibhu |
And there was a lint error that we shouldn't be using static context references as it may lead to leaks
|
Mark M. |
the only safe Context object to reference in a static field is the Application itself
|
Mark M. |
if you are holding onto anything else, that probably represents a memory leak
|
Mark M. |
("anything else" meaning "anything else as a Context", such as an Activity or Service instance)
|
Vibhu |
Does that mean that instead of holding a static Context reference, we can hold a static Application instance?
|
Mark M. |
in terms of getting past the Lint warning, I cannot say, as I have not encountered that warning
|
Mark M. |
in terms of avoiding memory leaks, a static field holding an Application will not be a leak
|
Mark M. |
each process gets one Application instance
|
Mark M. |
it is created when the process is created
|
Mark M. |
it is effectively "pre-leaked"; you cannot leak it further by having references to it
|
Vibhu |
Ok
|
Mar 2 | 9:05 AM |
Vibhu |
This is the link which inspired us to remove the static application context references https://www.philosophicalhacker.com/2015/07/14/...
|
Mark M. |
having only read the summary, I probably agree with that article
|
Mark M. |
I thought that you were comparing having static references to Context versus having static references to Application
|
Mark M. |
I agree that, ideally, you do not have static references to either of them
|
Mark M. |
at least not directly
|
Mark M. |
you might indirectly wind up with a static reference (e.g., through some third-party library)
|
Vibhu |
We refactored the code and now we are passing the context in methods as parameter which lead to a large amount of changes in files across the app
|
Vibhu |
and I just wants to be sure if I am going in right direction
|
Mar 2 | 9:10 AM |
Mark M. |
generally, yes
|
Mark M. |
having a static Application instance, or a static object that holds an Application, is necessary on occasion
|
Mark M. |
however, there should be a clear reason *why* it is necessary, and "we don't like typing" is not a reason
|
Mark M. |
so, for example, an event bus -- greenrobot's EventBus, LocalBroadcastManager, RxAndroid-based ones, etc. -- may need a reference to a Context to help deliver events on the main application thread
|
Mark M. |
and, usually, such an event bus is global in scope, and so is held in a static field, often hidden inside the event bus API
|
Mark M. |
here, the reason for having a static Application instance is to enable some key piece of functionality, and doing so in a way that avoids unnecessary memory leaks
|
Vibhu |
ok
|
Vibhu |
The lint error which made us this refactoring is "StaticFieldLeak"
|
Vibhu |
in terms of clean code, do you think having a lot of methods taking context is the way to go or not?
|
Mar 2 | 9:15 AM |
Mark M. |
well, in some cases, it may be that you need to pass a suitable Context to the constructor of some other class, so that object can hold onto that Context (or onto the Application that it gets from calling getApplicationContext() on the supplied Context)
|
Mark M. |
IOW, "no static Context fields" != "no Context fields"
|
Vibhu |
ok thanks! I think our approach is good so far
|
Vibhu |
I have one more question about the way Application class works
|
Mark M. |
go right ahead
|
Mar 2 | 9:20 AM |
Vibhu |
If we want to initialize something once per application life cycle, is onCreate method of Application class is good place to do that?
|
Mark M. |
generally, yes, with some caveats
|
Mark M. |
first, onCreate() is called on the main application thread; any work that you do in that method needs to be very very fast
|
Mark M. |
second, if you also have ContentProviders, and those ContentProviders need whatever you are doing in the Application, the timing gets a bit tricky
|
Vibhu |
what I mean to ask is that is it guaranteed to run 100% of time before any other code in the application runs, even after recovering from application crash or low memory scenarios?
|
Mark M. |
I am not certain what "low memory scenarios" means
|
Mark M. |
and I am not certain what "recovering from application crash" means, either
|
Mark M. |
onCreate() on Application will be called when the Application instance is created, which is part of setting up your process
|
Mark M. |
ContentProviders are also set up around this time
|
Mark M. |
everything else gets set up later
|
Mark M. |
so, outside of ContentProviders, onCreate() on Application gets in first, when the process is set up, and precedes anything you might be doing in activities, services, or receivers
|
Mar 2 | 9:25 AM |
Mark M. |
this will include when you get a fresh process forked after having your process terminated while in the background
|
Vibhu |
so for example if we initialize a logging library in onCreate and then application crashes, and then automatically restarts, will that make onCreate to be called again for Application?
|
Mark M. |
yes
|
Mark M. |
well, rephrase that: if by "automatically restarts", you mean that you get a fresh process, then yes
|
Mark M. |
I do not see "automatically restarts" in practice very much
|
Vibhu |
or if application was killed in background due to low memory and then system restarts the application when memory is available, will onCreate of application be called in that case too?
|
Mark M. |
yes
|
Mark M. |
because "killed in background" really means "process was terminated"
|
Mark M. |
and so when your app needs to run again, you get a fresh process and a fresh Application instance
|
Vibhu |
is there any case when application restores from bundle and not calling onCreate again?
|
Mark M. |
I do not know what "restores from bundle" means
|
Mark M. |
if you are getting a new process, you get a new Application and a fresh onCreate() call
|
Mark M. |
if you are not getting a new process, you do not get a new Application and a new onCreate() call
|
Mar 2 | 9:30 AM |
Vibhu |
Is there a possibility that our process is still running in background and all the singletons we initialized from Application are unloaded from memory?
|
Mark M. |
only if you are somehow "unloading" them yourself, from your own code
|
Mark M. |
or, those singletons are from third-party libraries, and *they* are "unloading" them through their own code
|
Mar 2 | 9:35 AM |
Vibhu |
ok
|
Mark M. |
for example, some caches will override onTrimMemory() and use those events to determine when to trim the caches back
|
Vibhu |
ok
|
Vibhu |
we are not doing that, we are initializing a logging library from onCreate of application class and are not sure if wants to do that from somewhere else too
|
Mark M. |
most likely that would not be necessary
|
Mark M. |
though the authors of the logging library may have recommendations
|
Vibhu |
ok
|
Mar 2 | 9:40 AM |
Vibhu |
Thanks Mark, those were the all questions I had
|
Mark M. |
OK
|
Vibhu |
Thanks for your time
|
Mark M. |
you are very welcome!
|
Vibhu | has left the room |
Mar 2 | 9:55 AM |
Mark M. | turned off guest access |