Well, that’s because Android is built in such a way that you don’t know for what reason your Application instance got created: whether it’s just to receive some broadcast message or to actually show UI to the user.
In the first step we aggregate all instances of Bootables that we have and add it to the library’s object:STEP_APPLICATION here just takes all critical Bootables.
After this process is finished we send our performance measurements to analytics service.
The second step launches from our SplashActivity and tells the library that is it safe to boot all non-critical Bootables:And that’s pretty much it what we have to do with bootstrap flow in our Application and SplashActivity classes.
Of course there is fallback strategy when something goes wrong, but I’m sure you can figure this out.
Everything else is done through creating new and modifying existing Bootables and it’s dependencies when needed.
Here’s the graph of our Bootables that are getting executed (orange are critical, blue gets loaded when we are in UI mode):The conclusionIntegrating this solution to our bootstrap flow helped us to achieve several things:Reduce TTI (time to interactable) by 10-15% in averageOrganize and segregate bootstrap flow into explicit stepsMeasure performance of each step and discover bottlenecksAbility to control bootstrap flow changes easily with static analysis on CIRight now we have 26 distinct Bootables in our app and after this separation we clearly see ways to reduce it’s number and improve bootstrap performance.
Implementing this library and integration process into our app was a big challenge for me and I’m satisfied with the results.
I would be glad to hear any feedback on the GitHub or (what is much more desirable) contributions.
Thank you all for your time reading this and remember to keep an eye at the time it takes your user to start interacting with your product.