Skip to content Skip to sidebar Skip to footer

Kotlin : Update View Using Function Created In Companion Object

I want to update view from my service class using static method inside my activity so when i have create method in companion object it will now allow to inherit view class inside c

Solution 1:

I want to update view from my service class using static method inside my activity so when i have create method in companion object it will now allow to inherit view class inside companion object

As you already are aware then, companion objects are static. Static methods, variables, etc, cannot access non-static variables.

Here's an example:

classSomething(var x: Int){
    // The companion object is staticcompanionobject{
        funsomeFun(){
            x = 3;//Unresolved reference: x
        }
    }
}

In Kotlin, x isn't found. Java does a slightly better job at explaining it:

privateint x;//getter and setterprivatestaticvoidsomeFun(){
    x = 3;//Non-static field cannot be referenced from static context
}

The same applies in Kotlin, but it handles it differently. The point, however, still applies: you cannot access non-static variables from a static class, method, field, or anything else.

To bring this back to your problem, you cannot access the non-static field titleMain from a static object, even if it's nested. It has to be non-static for you to access it.

Before I go on to a possible solution, I want to explain why you shouldn't use static methods at all when it comes to activities.

In order for you to access a non-static field in the activity, you need a static instance of the activity. Or a view for that matter. However, all of these have a Context in them. Context fields should never be static, and IntelliJ/Android Studio will warn you if you try. It can cause memory leaks, which would be the biggest problem here. It also makes instant run unusable, but that's not a problem unless you actually use it. See this Stack Overflow post.

Now, for the solution: Use callbacks. It's more complicated than using static methods, but it doesn't involve memory leaks

You didn't include that much code, so I've written most of it from scratch. It should still give you some pointers on getting started.

First off, you'll need to add an interface to the service, containing all the callback methods. It could be one, or it could be 100. Declare as many as you need, with or without return values and arguments.

Here is an example Service class. There are comments explaining what everything does.

classSomeService : Service(){
    privateval binder = SomeServiceBinder()
    privatevar callback: SomeServiceCallback? = null// The rest of the service/**
     * In this method, you return the binder instance created earlier. It's necessary
     * for the connection to the Activity
     */overridefunonBind(intent: Intent?): IBinder {
        // Do something here if necessaryreturn binder;
    }

    /**
     * Method containing example use of callbacks
     */overridefunonStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        // If a callback has been registered, call the callback// Could be done in a separate thread, after some action, before some action,// TL;DR: anywhere you'd like.
        callback?.updateUI(product)

        // The return value could of course be anything.return START_STICKY
    }

    /**
     * Register the callback, or null for removing it
     */funregisterCallback(callback: SomeServiceCallback?){
        this.callback = callback
    }

    /**
     * The binder. Contains a `getService` method, returning the active instance of the service.
     */innerclassSomeServiceBinder : Binder() {
        fungetService() = this@SomeService
    }

    /**
     * Add methods to this as you need. They can have arguments, or not. They can have a return type, or not. It's up to you
     */interfaceSomeServiceCallback{
        funupdateUI(product: Product);
    }
}

And finally, the activity. In addition to extending an Activity (here: AppCompatActivity), it also implements the callback interface.

In addition, it implements ServiceConnection. The ServiceConnection could also be an inner class, or declared as a field.

classSomeActivity : AppCompatActivity(), SomeService.SomeServiceCallback, ServiceConnection{
    /**
     * Stored externally to help with shutdown
     */lateinitvar someServiceIntent: Intent

    overridefuncallbackForSomething(product: Product) {
        println("Service called activity!")
        runOnUiThread{
            titleMain.text = product.title;
        }
    }

    overridefunonCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
        super.onCreate(savedInstanceState, persistentState)
        /**
         * The intent needs to be created here. if it's created outside, it might reference the context before it's
         * been initialized, which makes it throw an NPE
         */
        someServiceIntent = Intent(this, SomeService::class.java)
    }

    privatefunconnectToService(){

        startService(someServiceIntent)// This is the normal part. You need this to start the service// However, it doesn't register a ServiceConnection. In addition to that, you also need// to call bindService:
        bindService(someServiceIntent, this, Context.BIND_AUTO_CREATE)
    }

    privatefundisconnect(){
        //Equivalently, on shutdown, there's an extra call// First stop the service
        stopService(someServiceIntent)
        // Then unbind it
        unbindService(this)
    }


    overridefunonServiceConnected(name: ComponentName?, service: IBinder?) {
        println("The service is connected")
        /**
         * This uses an unsafe cast since there is just one service and one service binder. If you have multiple,
         * use a when statement or something else to check the type
         */val binder = service as SomeService.SomeServiceBinder? ?: return
        binder.getService().registerCallback(this)
    }

    overridefunonServiceDisconnected(name: ComponentName?) {
        TODO("Do something here if you want")
    }

}

Post a Comment for "Kotlin : Update View Using Function Created In Companion Object"