Office Hours — Today, March 2

Yesterday, March 1

Mar 2
8:50 AM
Mark M.
has entered the room
Mark M.
turned on guest access
8:55 AM
Vibhu
has entered the room
Mark M.
hello, Vibhu!
how can I help you today?
Vibhu
Hi Mark
View paste
Recently in our app we did some hygiene to handle static references to the app context.
Is there any advice on best way to deal with that?
Mark M.
I am not certain what you mean, sorry
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
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
if you are holding onto anything else, that probably represents a memory leak
("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
in terms of avoiding memory leaks, a static field holding an Application will not be a leak
each process gets one Application instance
it is created when the process is created
it is effectively "pre-leaked"; you cannot leak it further by having references to it
Vibhu
Ok
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
I thought that you were comparing having static references to Context versus having static references to Application
I agree that, ideally, you do not have static references to either of them
at least not directly
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
and I just wants to be sure if I am going in right direction
9:10 AM
Mark M.
generally, yes
having a static Application instance, or a static object that holds an Application, is necessary on occasion
however, there should be a clear reason *why* it is necessary, and "we don't like typing" is not a reason
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
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
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
The lint error which made us this refactoring is "StaticFieldLeak"
in terms of clean code, do you think having a lot of methods taking context is the way to go or not?
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)
IOW, "no static Context fields" != "no Context fields"
Vibhu
ok thanks! I think our approach is good so far
I have one more question about the way Application class works
Mark M.
go right ahead
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
first, onCreate() is called on the main application thread; any work that you do in that method needs to be very very fast
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
and I am not certain what "recovering from application crash" means, either
onCreate() on Application will be called when the Application instance is created, which is part of setting up your process
ContentProviders are also set up around this time
everything else gets set up later
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
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
well, rephrase that: if by "automatically restarts", you mean that you get a fresh process, then yes
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
because "killed in background" really means "process was terminated"
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
if you are getting a new process, you get a new Application and a fresh onCreate() call
if you are not getting a new process, you do not get a new Application and a new onCreate() call
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
or, those singletons are from third-party libraries, and *they* are "unloading" them through their own code
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
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
though the authors of the logging library may have recommendations
Vibhu
ok
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
9:55 AM
Mark M.
turned off guest access

Yesterday, March 1

 

Office Hours

People in this transcript

  • Mark Murphy
  • Vibhu