My app consists of two activities: SignInActivity and MainActivity. SignInActivity lets the user sign in, and initializes a bunch of important variables the app needs to function properly. MainActivity contains a bunch of fragments that make up the actual app. These fragments use a MVVM architecture with ViewModel
s. The Fragment
classes load information from their ViewModels to display on the screen.
One Fragment
, AppleFragment, loads the type of apple (that the user previously inputted) by calling vm.getAppleType().getName()
. AppleFragment then displays the type of apple on the screen. The user may only navigate to AppleFragment after he/she has set the type of apple.
Let's say a user presses the home button while using my app in MainActivity and AppleFragment. The app will be moved into the background and might be killed by the Android OS to save memory. If this is the case, and the user then goes to the Overview screen (i.e. the square button), and selects my app to open, Android will restart the Activity that was last open (MainActivity), and also the fragment that was last open (AppleFragment), but all variables (including the ones in the ViewModels) will be fresh - i.e. start from scratch.
Since AppleFragment loads vm.getAppleType().getName()
in onViewCreated(), and the ViewModel is completely blank - remember Android destroyed everything to save memory - vm.getAppleType().getName()
results in a NPE and the app crashes.
To mitigate this, I have MainActivity check if the important app variables have been initialized, and if not, start SignInActivity. The idea being that in the situation detailed above, the user would be redirected to SignInActivity, and the app would populate the important variables when the user signs in. The user would not be able to navigate to AppleFragment until they have set the apple type which the ViewModel can then give out to AppleFragment to display.
This approach doesn't work completely, because startActivity() schedules SignInActivity, but does not start it immediately - especially not until all of MainActivity's lifecycle methods have finished running. It seems that as part of MainActivity's onStart() method, the last viewed fragment, AppleFragment, is loaded. This is where we get into trouble because AppleFragment calls vm.getAppleType().getName()
in its onViewCreated method leading to the NPE and app crash.