For my Android project, I need global singleton Cache object to access data about a user through the app.
A problem occurs when an app goes into the background and after some time of using other apps I try to open app variables in Cache objects are null. Everything is okay when I kill the app and open it again. I'm using dependency injection to access Cache object. Why doesn't app start again if that happened? Is there some annotation to keep cache variable even in low memory conditions?
This is my Cache class
class Cache {
var categories : Array<BaseResponse.Category>? = null
var user : BaseResponse.User? = null
var options : BaseResponse.OptionsMap? = null
var order: MenuOrderDataModel? = null
}
This is Storage module for DI
@Module class StorageModule {
@Singleton @Provides fun getSharedPrefs(context: Context): SharedPreferences {
return PreferenceManager.getDefaultSharedPreferences(context)
}
@Singleton @Provides fun getCache() : Cache = Cache()
}
I inject object @Inject lateinit var cache: Cache
and then populate with user data in splash screen.
Edit - added code snippets from Application and launch activity
class MyApp : Application() {
val component: ApplicationComponent by lazy {
DaggerApplicationComponent
.builder()
.appModule(AppModule(this))
.build()
}
companion object {
@JvmStatic lateinit var myapp: MyApp
}
override fun onCreate() {
super.onCreate()
myapp= this
Fabric.with(this, Crashlytics())
}
}
Splash activity:
class SplashActivity : AppCompatActivity(), View.OnClickListener {
@Inject lateinit var viewModel : ISplashViewModel
private lateinit var disposable : Disposable
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_splash)
MyApp.myapp.component.inject(this)
}
You're getting crashes because you initialize those variables in one Activity, and expect it to be set always, in the other Activity.
But Android doesn't work like that, you can easily end up crashing because after low memory condition happens, only the current Activity gets recreated at first, previous Activity is recreated on back navigation, and all static variables are nulled out (because the process is technically restarted).
Try it out:
put your application in background with HOME button
click the TERMINATE button on Logcat tab
You'll experience this phenomenon.
In Android Studio 4.0, after you use Run
from Android Studio instead of starting the app from launcher, the Terminate button SOMETIMES works a bit differently and MIGHT force-stop your app making it forget your task state on your attempt. In that case, just try again, launching the app from launcher. It will work on your second try.
You can also trigger the "Terminate Application" behavior from the terminal, as per https://codelabs.developers.google.com/codelabs/android-lifecycles/#6, it looks like this:
$ adb shell am kill your.app.package.name
In the new Logcat (Android Studio Electric Eel and above), the "terminate process" button is removed, and was moved into the Device Monitor tab ("Kill Process").
Solution: check for nulls and re-initialize things in a base activity (or in LiveData.onActive), or use onSaveInstanceState
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With