Home > Blockchain >  Android Kotlin: Having a global Context object for all activities (best practice)
Android Kotlin: Having a global Context object for all activities (best practice)

Time:07-16

I have a global app settings class as follows:

class AppSettings : MultiDexApplication() {

    override fun onCreate() {
        super.onCreate()
        instance = this
        resourses = applicationContext.resources
        outputPathCache = cacheDir.absolutePath
    }

    companion object {
        lateinit var instance: AppSettings
            private set

        val context: Context
            get() { return activityContext.get()!! }

        lateinit var activityContext: WeakReference<Context>

        var database: SQLiteDatabase? = null

        var resourses: Resources? = null
            private set

        lateinit var dialog: AlertDialog

        const val defLanguage = Enum.Language.ENGLISH
        const val defIdLanguage = Enum.LanguageId.ENGLISH
        const val screenshotFilename = "xxx"

        const val actionBarTitleColor = "#0D0D0D"
        const val footerColor = "#8a8a8a"
        const val activityBackground = "#ffffff"

        ... whatever
    }
}

And as you see I have a static Context variable as follows:

lateinit var activityContext: WeakReference<Context>

(I use WeakReference so the IDE doesn't complain about memory leaks).

And I have a constant Context like the next:

val context: Context
                get() { return activityContext.get()!! }

I assign a value for the first time to activityContext in SplashActivity as follows (I do this because the first activity is a OnBoarding class that doesn't inherit from BaseActivity):

AppSettings.activityContext = WeakReference(this)

The same in BaseActivity onCreate (most of my activities inherit from this class):

AppSettings.activityContext = WeakReference(this)

And then, in any activity which extends BaseActivity I can use the context simply like this:

AppSettings.context

For the activities that doesn't inherit from BaseActivity I just initialise the context to be used in the activity in the same way as in Base, so I can always get it as "AppSettings.context".

The reason of not simply using "this" in all activities to get context (or to use any sort of Context creation in Base) is that I'm using MVVM and there are classes outside activities (like ViewModel) with methods that may need a context, and I just don't wan't to pass it as a parameter (this is why I'm expecting to have a global context that can be accessed anywhere).

Although I have just finished and I haven't fully tested yet, it is apparently working great, but I wonder to know if this is the recommended way to deal with this, or if there is a better approach to have a global Context.

CodePudding user response:

There are some ways to achieve that, but I believe the most encouraged by google is with the dependency injection library dagger-hilt, which isn't hard to set-up, but saves a lot of time and prevents possible memory-leaks. In order to inject context into any class later you just need to do:

class ExampleClass @Inject constructor(@ApplicationContext val context: Context) {}
  • Related