How to bind external library class with callback in Hilt?

Viewed 520

I'm a beginner in Hilt. I have a library which takes in an interface. The library does some operation and invokes the interface callback. I have an activity which invokes this library by passing the interface implementation. I'd like to know how to inject this using Hilt.

Interface in library

 interface InterfaceInLibrary() {

   fun callback1()
   fun callback2(/*params */)

}

Activity

class MyActivity: InterfaceInLibrary() {

  override fun onCreate(savedInstanceState: Bundle?) {
   
  //library initialization
  val myLibraryClass = MyLibraryClass.getInstance(this) //passing the InterfaceInLibrary implementation

  }

  override fun callback1() {
    Toast.makeText(this, "callback1", Toast.LENGTH_LONG).show()
  }
  
  override fun callback2() {
    Toast.makeText(this, "callback2", Toast.LENGTH_LONG).show()
  }

}

I would like to know how to inject MyLibraryClass in MyActivity using Hilt.

1 Answers

The only possible way I know (or at least how I am handling this use-case in my projects) is to field inject the concrete class that invokes the interface and then let the activity implement the concrete class and inherit from the callback. Since your interface and your concrete class look kinda weird, I will provide a full implementation here. Let's assume we have the following interface:

Interface

interface IMyCallbackInterface {
    fun callbackWithoutParameters()
    fun callbackWithParameters(value: String)
}

Then, you need some class to invoke this callback. In my case, this was always a recylerview.adapter, but we will use somethin easier:

Invoking class

class MyInvokingClass @Inject constructor() {
     // this interface will be initialized by our activity
     private lateinit var callbackListener: IMyCallbackInterface

     // This function invokes the first callback
     fun someFunctionThatInvokesCallbackWithoutParameters() {
         // do some stuff
         callbackListener.callbackWithoutParameters()
     }

     // This function invokes the second callback
     fun someFunctionThatInvokesCallbackWithParameters() {
         // do some stuff
         callbackListener.callbackWithParameters(value = "Hello")
     }
     
     // This will be called from our activity to initialize the callback
     fun initializeCallback(callbackOwner: IMyCallbackInterface) {
         this.callbackListener = callbackOwner
     }
}

Then, you need to field inject the class and inherit from the callback inside your activity

Activity or Fragment

class MyActivity : IMyCallbackInterface {

     @Inject lateinit var invokingClass: MyInvokingClass

     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate()
         setContentView(...)
         
         // Since MyActivity implements the interface
         // it is an instance of it. So you can simply
         // say, that the "owner" of the callback is the activity
         invokingClass.initializeCallback(this@MyActivity)
     }

      override fun callbackWithoutParameters() {
          // do some stuff
      }

      override fun callbackWithParameters(value: String) {
          // do some stuff with string
      }
}

Because our Activity inherits from the callback and we said in onCreate() that the interfaceOwner of MyInvokingClass is the activity, every time the callback gets invoked, the interface functions inside the activity will be invoked as well.

Related