Dagger 2 : Memahami Component & Constructor Injection
Pada kesempatan kali ini saya akan mencoba membawa materi mengenai Dagger 2 melalui pengalaman saya menggunakan nya, Memang terkesan terlambat karena sudah ada library yang berdiri diatas Dagger 2 seperti Hilt yang memudahkan kita menggunakan nya.
Tapi toh tidak ada salahnya membawa materi ini kembali hehehe.
Ohiya bagi temen temen yang belum tau apa itu Dagger, Dagger adalah library Dependency Injection yang populer untuk Java, Kotlin, dan Android yang dikelola oleh Google.
Sedangkan Dependecy Injection(DI) adalah teknik yang banyak digunakan dalam pemrograman dan cocok untuk pengembangan Android. Dengan mengikuti prinsip DI, Anda meletakkan dasar untuk arsitektur aplikasi yang baik.
Okay setelah kita memahami apa itu DI & Dagger yuk kita kembali ke topik Memahami Component & Constructor Injection
Case
- Monster. Interface ini akan kita gunakan sebagai base untuk monster lain nya & hanya mempunyai 2 fungsi setter & getter monster name
interface Monster {
fun setMonsterName(name: String)
fun getMonsterName(): String
}
2. MonsterAttribute. Kita akan membuat Dragon class dependensi terhadap class ini & Class ini tidak berisi apa-apa hanya sebagai contoh agar bisa mempraktekan DI
class MonsterAttribute
3. Dragon. Class ini menciptakan dragon sekaligus contoh dari Constructor Injection hehehe
private const val TAG = "Dragon"
class Dragon(private val attribute: MonsterAttribute) : Monster {
private var _name: String = ""
val name get() = _name
override fun setMonsterName(name: String) {
_name = name
}
override fun getMonsterName(): String {
return "$TAG named $name"
}
}
4. Usecase. Cara normal summon Dragon adalah seperti ini
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val attribute: MonsterAttribute = MonsterAttribute()
private val myMonster: Monster = Dragon(attribute)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
myMonster.setMonsterName("jojo")
binding.tvMain.text = myMonster.getMonsterName()
}
}
Dengan contoh di atas kita bisa summon Dragon dengan mudah menggunakan konsep dependency injection by hand atau manual dependency injection.
Tapi bagaimana bila Dragon class membutuhkan banyak dependensi class pada constructor nya ? Dan kita tidak bisa membuatnya langsung by hand atau dengan manual ?
Dagger to The Rescue
Sekarang kita anggap saja MonsterAttribute Class adalah class yang tidak bisa kita build by hand
- Constructor Injection. Tambahkan anotasi @Inject ke constructor Dragon class sehingga Dagger tahu cara membuat Dragon
// @Inject memberi tahu Dagger cara membuat instance dari object ini
class Dragon @Inject constructor(private val attribute: MonsterAttribute) : Monster// @Inject memberi tahu Dagger cara membuat instance dari object ini
class MonsterAttribute @Inject constructor()
Mengapa class MonsterAttribute juga perlu ditambahkan anotasi @Inject ?
Jawabannya simpel : Dagger tahu cara membuat instance Dragon, tetapi tidak tahu cara membuat dependensinya yaitu MonsterAttribute. Jadi kita juga perlu memberi anotasi @Inject agar Dagger tahu cara membuatnya
2. Component. kalau @Inject tadi adalah cara Dagger membuat instance maka @Component bisa di bilang adalah tempat dimana kita menggunakan seluruh dependesi yang telah kita buat. Oh iya untuk membuat Dagger Component kita memerlukan interface ya !
@Component
interface DragonComponent {
fun getDragon():Dragon
}
3. Perubahan. Dragon class yang baru akan menjadi seperti ini :
private const val TAG = "Dragon"
class Dragon @Inject constructor(private val attribute: MonsterAttribute) : Monster {
private var _name: String = ""
val name get() = _name
override fun setMonsterName(name: String) {
_name = name
}
override fun getMonsterName(): String {
return "$TAG named $name"
}
}
MonsterAttribut class yang baru akan menjadi seperti ini :
class MonsterAttribute @Inject constructor()
4. Penggunaan. Setelah step 1 hingga 3 sudah kita lakukan jangan lupa build project ya supaya Dagger dapat generete code yang sudah kita buat
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var myInjectedMonster:Dragon
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val component:DragonComponent = DaggerDragonComponent.create()
myInjectedMonster = component.getDragon()
myInjectedMonster.setMonsterName("jojo")
binding.tvMain.text = myInjectedMonster.getMonsterName()
}
}
Kalau kita perhatikan ada object baru yang bernama DaggerDragonComponent itu lah code yang di generate oleh Dagger agar bisa kita gunakan untuk summon Dragon kita, Kalau ada yang penasaran dengan generated code nya bisa lihat di bawah ini ya :
public final class DaggerDragonComponent implements DragonComponent {
private DaggerDragonComponent() {
}
public static Builder builder() {
return new Builder();
}
public static DragonComponent create() {
return new Builder().build();
}
@Override
public Dragon getDragon() {
return new Dragon(new MonsterAttribute());}
public static final class Builder {
private Builder() {
}
public DragonComponent build() {
return new DaggerDragonComponent();
}
}
}
Okay itu saja materi yang bisa saya sampaikan memang mungkin sedikit membingungkan & cara mengatasinya adalah langsung Praktek ! apalagi praktek langsung dengan real case. Materi kali ini pun saya sadari hanya sebagian kecil saja dari Dagger karena masih banyak sekali yang perlu kita pelajari.
untuk memahaminya lebih dalam bisa lihat repo saya disini ya
Memang dengan adanya Hilt kita sangat terbantukan, tapi walaupun begitu kita tetap perlu mengetahui dasar-dasar penggunaan pada Dagger agar kita bisa maksimal menggunakan Hilt.
Terimakasih !
Sampai jumpa lagi