Kotlin Dependency Injection (Dagger)

Dagger provide dependency injection using the annotations.
            1) @Inject
            2) @Module
            3) @Provides
            4) @Component

1) Inject  defines which object you want to inject to your view.
2) Modules are responsible to provide appropriate object to the injected fields.
3) Provides returns the object from the method define in the module class.
4) Component is the bridge between injected object and Object class(Module).

Now that we understand a bit, we can go forward with dependency injection exploration using one example.
First you have to add the below gradle to your project :-

Dagger
implementation 'com.google.dagger:dagger:2.13'
kapt 'com.google.dagger:dagger-compiler:2.13'

Apply plugin
          apply plugin: 'kotlin-kapt’


Step 1) Create the utility class which we want to use in the activity. In my example i m using the preference class.

@Singleton
class Preference @Inject constructor(application: Application) {
private var mPreference: SharedPreferences =
application.getSharedPreferences(application.getString(R.string.app_name), MODE_PRIVATE)

fun putData(keyword: KEYWORD, data: Boolean) {
val editor = mPreference.edit()
editor.putBoolean(keyword.toString(), data)
editor.apply()
}
    fun getBoolean(keyword: KEYWORD): Boolean {

        return mPreference.getBoolean(keyword.toString(), false)
    }

    fun remove(keyword: KEYWORD) {

        val editor = mPreference.edit()

        editor.remove(keyword.toString())

        editor.apply()
    }

    fun clear() {

        val editor = mPreference.edit()

        editor.clear()

        editor.apply()
    }

    fun isContains(keyword: KEYWORD): Boolean {

        return mPreference.contains(keyword.toString())
    }


    enum class KEYWORD {

        USERNAME
    }

}

Step 2) Now we create the module class for the dependence injection as below:-

@Module class ActivityModule constructor(private val application: Application) {

@Provides
fun getApplication(): Application {
return application
}

}

   In this example, ActivityModule class provide the object of application.

Step 3)  After Creating the module class we have to add the component class for this module.

@Singleton
@Component(modules = [(ActivityModule::class)])
interface OnActivityComponent {
    fun inject(activity: BaseActivity)

    fun getPreference(): Preference
}
  
Step 4) Now use the component inside your BaseActivity class.
  
    abstract class BaseActivity : AppCompatActivity(), OnActivityCallback {

    @Inject
    lateinit var mPrefrence: Preference

    private lateinit var mView: View;
    private lateinit var mComponent: OnActivityComponent

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val mBinding: ViewDataBinding = DataBindingUtil.setContentView(this, getLayout())
        setBinding(mBinding)
        mView = mBinding.root
        initActivity()
        initComponent()
    }

    private fun initComponent() {
        mComponent = DaggerOnActivityComponent.builder()
                .activityModule(ActivityModule(this.application))
                .build()
         mComponent.inject(this)
}

    abstract fun initActivity()

    abstract fun setBinding(binding: ViewDataBinding)

    abstract fun getLayout(): Int

    override fun toast(message: String) {
        Toast.makeText(this, message, Toast.LENGTH_LONG).show()
    }

    override fun snackBar(message: String) {
        Snackbar.make(mView, message, Snackbar.LENGTH_LONG).show()
    }

}
Main Activity.kt

class MainActivity : BaseActivity(), View.OnClickListener {
private lateinit var mBinding: ActivityMainBinding

   override fun setBinding(binding: ViewDataBinding) {
         mBinding = binding as ActivityMainBinding
   }

   override fun getLayout(): Int {
    return R.layout.activity_main
   }

    override fun initActivity() {
           mBinding.actMainTextview.text = getString(R.string.app_name)
          mBinding.click = this
   }

   override fun onClick(v: View) = when (v.id) {
        R.id.act_main_textview -> {
          mPrefrence.putData(Preference.KEYWORD.USERNAME, "Mahavir")
          toast(mPrefrence.getString(Preference.KEYWORD.USERNAME))
          }
       else -> {
        toast("Not found")
      }
  }
}

Comments