Search code examples
kotlinconstructorstaticandroid-contextcompanion-object

kotlin pass context to static constructor


I want to pass context to my custom class means Utils for some functions.I want create my Custom Toast to show my messages.for this I need context but my toast function is static and can not use it because we can get non static variable in static functions.how can pass context to Utils class and use context in static functions in Utils class? I know that I can get the context in show instead of Utils class but I want get context in Utils class and use it for others functions too. in my codes the context is unreachable in show function

class Utils(var context:Context){
    companion object{
        fun show(){
            Toast.makeText(context,message,Toast.LENGTH_SHORT).show()
        }
    }
}

Solution

  • To have a Context be available to multiple static or top-level functions, you must store it in a static property. This means you will have to initialize your functions through some static function or property setter, not a class constructor.

    You can do something like this:

    object Utils {
        lateinit var context: Context
            set(value) { field = value.applicationContext }
    
        fun show(){
            Toast.makeText(context,message,Toast.LENGTH_SHORT).show()
        }
    }
    

    It's important to strip the context down to an application context like I did in the setter above so you won't leak any Activities or other subclasses of Context. This is because the static property will outlive the lifecycle of any Activities or views.

    You must set the Utils.context parameter at the entry point of your app. If it has only one task root Activity, you can put it in onCreate of that Activity. If your app has multiple entry points, then you probably want to subclass Application and put it in the onCreate of your Application.

    Alternatively, it might be safer to do it like this, so you can't possibly create an uncaught exception:

    object Utils {
        var context: Context
            set(value) { field = value.applicationContext }
    
        fun show(){
            context?.let {
                Toast.makeText(it,message,Toast.LENGTH_SHORT).show()
            } ?: Log.e("Utils", "Called show() before setting the context.")
        }
    }
    

    Example:

    // In the main entry point to your app (the launcher Activity):
    override fun onCreate() {
        super.onCreate()
        Utils.context = this
    
        //...
    }
    
    // And when you want to call one of its functions:
    Utils.show()