Saturday, September 16, 2017

Implementasi Dagger 2 Android Pada MVP

Implementasi Dagger 2 Android Pada MVP


Dagger adalah suatu mekanise untuk menerapkan Dependency Injection tanpa membuat penulisan kode menjadi  berulang – ulang, atau dengan kata lain untuk menyederhanakan Dependency Injection. Sedangkan menurut website nya :

Dagger is a fully static, compile-time dependency injection framework for both Java and Android. It is an adaptation of an earlier version created by Square and now maintained by Google.
Apa itu Dependency  Injection? Menurut Om Wikipedia :
Dependency Injection is a technique whereby one object supplies the dependencies of another object. A dependency is an object that can be used (a service). An injection is the passing of a dependency to a dependent object (a client) that would use it.
Fungsi dari Dependency Injection yaitu menginjeksi bagian-bagian tertentu dalam aplikasi sehingga dapat mempermudah mengatur flow sebuah program .

Contoh paling simple dari Dependency Injection, seperti ini :
 Luas luas = new Luas(4, 5);  
 Volume volume = new Volume(luas, 3);  
 int hitungVolume = volume.hitungVolume();  

Bisa dilihat bahwa untuk kelas Volume memerlukan sebuah kelas bernama Luas.Pada kasus ini kita "menyuntikan" kelas Luas ke kelas Volume, karena kelas Volume memiliki "ketergantungan" dengan kelas Luas.Seperti ini contoh sederhana dari dependency injection.

Sedangkan MVP itu sendiri adalah singkatan dari Model View Presenter.Apa itu MVP?Menurut Om Wikipedia :

MVP is a user interface architectural pattern engineered to facilitate automated unit testing and improve the separation of concerns in presentation logic :
  • The model is an interface defining the data to be displayed or otherwise acted upon in the user interface.
  • The view is a passive interface that displays data (the model) and routes user commands (events) to the presenter to act upon that data.
  • The presenter acts upon the model and the view. It retrieves data from repositories (the model), and formats it for display in the view.
Untuk lebih jelasnya, mungkin bisa dibantu dengan gambar ini :
Jadi bisa dilihat bahwa Presenter sebagai Mediator atau penghubung antara Model dengan View. Dimana Model sebagai Business Logic dan segala sesuatu yang berhubungan dengan data, contohnya query ke database lokal android, seperti Sqlite atau Realm. Sedangkan View untuk menampilkan output dari proses yang dihasilkan dari hasil hubungan antara Presenter dan Model, atau menerima inputan untuk diteruskan ke Presenter sehingga Presenter dan Model bisa berhubungan. Untuk lebih jelasnya bisa dilihat pada gambar di bawah ini :

Oke, selanjutnya kita kembali ke topic awal, yaitu Implementasi Dagger 2 pada Android.

Bumbu pertama yang akan kita siapkan di dalam gradle project kita adalah adalah :
 compile 'com.google.dagger:dagger:2.11'   
 annotationProcessor "com.google.dagger:dagger-compiler:2.11"  

 Untuk membantu memahami apa isinya Dagger, bisa dilihat di gambar ini :


Ada beberapa annotasi di dalam dagger yaitu :
  • @Module : kelas yang menyediakan dependencies
  • @Provides : method-method yang ada di kelas @Module
  • @Scope : anotasi Java untuk menginisialisasikan object yang akan diinjeksikan
  • @Inject : sebuah request dependency, bisa berupa construktor, method, maupun field
  • @Component : sebuah jembatan penghubung antara module dan injection.
Oke, sekarang kita akan coba untuk memasaknya.Dalam kasus ini, kita akan membuat sebuah kalkulator yang sangat sangat sederhana.

Pertama kita siapkan apa saja yang ingin kita provide ke dalam kelas Module.Di dalam kelas Module, kita akan mem-provide kelas - kelas apa saja yang ingin kita injeksikan. Contoh kelas Module adalah seperti ini :
 @Module  
 public class CalculatorModule {  
   private Application application;  
   public CalculatorModule(Application application) {  
     this.application = application;  
   }  
   @Provides  
   @Singleton  
   Application providesApplication() {  
     return application;  
   }  
   @Named("ApplicationContext")  
   @Provides  
   @Singleton  
   Context provideContext() {  
     return application;  
   }  
   @Provides  
   @Singleton  
   CalculatorUtil providesCalculatorUtil() {  
     return new CalculatorUtil();  
   }  
   @Provides  
   @Singleton  
   NotesModel providesNotesModel() {  
     return new NotesRepository();  
   }  
 }
Selanjutnya kita akan membuat kelas Component. Kelas Component ini berfungsi untuk menghubungkan antara module dan injection. Contohnya adalah seperti ini :
 @Singleton  
 @Component(modules = {CalculatorModule.class, PreferenceModule.class, RealmModule.class})  
 public interface CalculatorComponent {  
   void injectCalculatorActivity(CalculatorActivity activity);  
   void injectNotesActivity(NotesActivity activity);  
 }  
Kemudian kita akan "menyuntik" pada kontruktor kelas Presenter dan Model yang telaj kita siapkan.Yang pertama kita akan inject kelas Model. Contohnya :
 @Singleton  
 public class CalculatorRepository implements CalculatorModel {  
   private CalculatorUtil calculatorUtil;  
   private PreferenceManager preferenceManager;  
   @Inject  
   public CalculatorRepository(CalculatorUtil calculatorUtil,  
                 PreferenceManager preferenceManager) {  
     this.calculatorUtil = calculatorUtil;  
     this.preferenceManager = preferenceManager;  
   }  
 }  
Penjelasan untuk code di atas, kelas CalculatorUtil sudah kita provide di bagian atas :
 @Provides   
   @Singleton   
   CalculatorUtil providesCalculatorUtil() {   
    return new CalculatorUtil();   
   }   
Sedangkan kelas PreferenceManager, kita provide di dalam kelas PreferenceModule.Untuk isi dari kelas PreferenceModule adalah :
 @Module  
 public class PreferenceModule {  
   @Named("PreferenceInfo")  
   @Provides  
   @Singleton  
   String providePreferenceName() {  
     return "CalculatorPreference";  
   }  
   @Provides  
   @Singleton  
   PreferenceManager providePreferenceManager(@Named("ApplicationContext") Context context,  
                         @Named("PreferenceInfo") String preferenceName) {  
     return new PreferenceManager(context, preferenceName);  
   }  
 }  
Untuk isi kelas PreferenceManager :
 public class PreferenceManager {  
   private SharedPreferences sharedPreferences;  
   public PreferenceManager(Context context,  
                String preferenceName) {  
     sharedPreferences = context.getSharedPreferences(preferenceName, Context.MODE_PRIVATE);  
   }  
 }  
Selanjutnya kita akan menginject konstruktor pada Presenter, contohnya adalah seperti ini :
 public class CalculatorPresenter implements CalculatorContract.Presenter {  
   private CalculatorContract.View view;  
   private CalculatorModel model;  
   private PublishSubject<Calculator> calculatorSubject = PublishSubject.create();  
   private PublishSubject<String> resultSubject = PublishSubject.create();  
   @Inject  
   public CalculatorPresenter(CalculatorRepository model) {  
     this.model = model;  
   }  
 }  
Oke, persiapan sedikit lagi selesai. Sebelum kita menginjeksikan bahan - bahan yang telah kita siapkan, kita build dulu projek kita, supaya dagger bisa mengenerate kelas - kelas yang telah kita siapkan tadi. Dan jangan lupa berdoa supaya tidak gagal build. Salah 1 contoh gagal build adalah seperti ini (kasusnya method providesCalculatorUtil saya hapus dari Module di atas) :






Hal ini disebabkan jika CalculatorUtil belum di - provide di dalam kelas Module, sehingga dimarahin oleh Android Studio nya.

Jika build anda sukses, langkah selanjutnya adalah membuat kelas Injector dan memanggil kelas tersebut ke dalam kelas Application.
 public class Injector {  
   private CalculatorComponent appComponent;  
   private CalculatorComponent createComponent(Application application) {  
     return DaggerCalculatorComponent.builder()  
         .calculatorModule(new CalculatorModule(application))  
         .preferenceModule(new PreferenceModule())  
         .realmModule(new RealmModule())  
         .build();  
   }  
   public void setAppComponent(Application application) {  
     if (getAppComponent() == null) {  
       setAppComponent(createComponent(application));  
     }  
   }  
   public CalculatorComponent getAppComponent() {  
     return appComponent;  
   }  
   public void setAppComponent(CalculatorComponent appComponent) {  
     this.appComponent = appComponent;  
   }  
 }  

 public class DaggerApp extends Application {  
   private Injector injector;  
   @Override  
   public void onCreate() {  
     super.onCreate();  
     injector = new Injector();  
     injector.setAppComponent(this);  
   }  
   public Injector getInjector() {  
     return injector;  
   }  
 }  
Sekarang saatnya menginjeksikan ini semua ke dalam View. Untuk menginjeksikan ke dalam View, cukup mudah.Cukup deklarasikan variabelnya dan menambahkan annotasi @Inject.
 @Inject  
 CalculatorPresenter presenter;  
Dan tambahkan 
  ((DaggerApp) getApplication()).getInjector().getAppComponent().injectCalculatorActivity(this);  
Untuk lengkapnya seperti ini :
 @Inject  
 CalculatorPresenter presenter;  
   @Override  
   protected void onCreate(@Nullable Bundle savedInstanceState) {  
     super.onCreate(savedInstanceState);  
     ((DaggerApp) getApplication()).getInjector().getAppComponent().injectCalculatorActivity(this);  
     setContentView(R.layout.activity_calculator);  
     presenter.setView(this);  
   }  
Selamat!Anda telah berhasil mengimplementasikan dagger 2 ke dalam MVP.Yeay!Cukup panjang jika dibaca?Ya...yang ngetik juga capek soalnya.. :D

Semoga apa yang saya share bisa berguna di kemudian hari.

Untuk url github bisa dilihat di sini :
SampleDaggerMVP

Saya mengambil beberapa referensi dari sini dan mohon maaf jika mungkin ada yang lupa saya cantumkan.

  • http://www.tinmegali.com/en/model-view-presenter-android-part-1/
  • https://android.jlelse.eu/android-mvp-for-beginners-25889c500443
  • https://code.tutsplus.com/tutorials/how-to-adopt-model-view-presenter-on-android--cms-26206
  • http://hannesdorfmann.com/mosby/mvp/
  • https://upday.github.io/blog/model-view-presenter/
  • https://medium.com/@be.betr.codr/android-mvp-survival-guide-b2094ab79f78
  • https://google.github.io/dagger/users-guide.html
  • https://blog.mindorks.com/introduction-to-dagger-2-using-dependency-injection-in-android-part-1-223289c2a01b
  • https://blog.mindorks.com/introduction-to-dagger-2-using-dependency-injection-in-android-part-2-b55857911bcd
  • https://medium.com/@Miqubel/understanding-dagger-2-367ff1bd184f
  • https://www.thedroidsonroids.com/blog/android/example-realm-mvp-dagger/
  • https://guides.codepath.com/android/Dependency-Injection-with-Dagger-2#dependent-components-vs-subcomponents
  • http://mobologicplus.com/dagger2-dependency-injection-mvp-android/
  • https://www.techyourchance.com/dagger-2-scopes-demystified/


No comments:

Post a Comment