Dagger2 Android ---基礎(如何使用)
該文章預設你已經掌握了Dagger2的常規使用。
如果對Dagger2的概念還不是很清楚,可以參考:
- ofollow,noindex">Dagger2 基礎依賴注入框架
- Dagger2 重點概念講解、融合篇
- Dagger2 終結篇
Dagger Android產生的原因??
- 物件使用者如果需要使用 Inject 註解生成的物件,需要知道其注入器(比如:DaggerxxxComponent),它打破了依賴注入的原則:一個類不應該知道如何注入它。
- 隨著專案程式碼的增多,類似 DaggerxxxComponent.buider().build().inject() 這樣的模板程式碼也會越來越多,使得後期很難重構。
Dagger2 2.1x新特性
解決了Dagger2 2.10之前的兩個明顯的缺陷, 被注入者不需要知道其注入者 。
依賴
//dagger2 依賴 implementation 'com.google.dagger:dagger:2.16' //dagger2 android依賴,一般直接依賴dagger-android-support,其內部預設依賴了dagger-android //implementation 'com.google.dagger:dagger-android:2.16' //添加了android support的支援 implementation 'com.google.dagger:dagger-android-support:2.16' //dagger註解處理器 annotationProcessor 'com.google.dagger:dagger-compiler:2.16' //dagger android註解處理器 annotationProcessor 'com.google.dagger:dagger-android-processor:2.16'
使用步驟
1. 被依賴類:在建構函式上使用 @Inject
註解宣告
public class Student { private String name; @Inject public Student() { } public String getName() { return name; } public void setName(String name) { this.name = name; } }
2. 使用依賴物件
public class MainActivity extends AppCompatActivity { private static final String TAG = MainActivity.class.getSimpleName(); @Inject Student student; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.e(TAG, "student ---- " + student.toString()); } }
如果直接這樣執行肯定是直接NullPoint,因為student還沒有被注入到MainActivity之中。
那Student物件又是如何注入的呢?
3. 實現依賴物件和使用者的繫結
-
自定義Application繼承DaggerApplication(注意導包,使用dagger.android.support.DaggerApplication)
這一步是實現自動注入的前提
public class DemoApp extends DaggerApplication { @Override protected AndroidInjector<? extends DaggerApplication> applicationInjector() { return null;//這裡先暫時返回null } }
-
我們知道需要將物件注入到使用者之中,要通過Component,那我們先建立MainComponent,使用
@SubComponent
註解(為什麼是使用SubComponent呢??)@Subcomponent public interface MainComponent extends AndroidInjector<MainActivity> { @Subcomponent.Builder abstract class Builder extends AndroidInjector.Builder<MainActivity>{} }
這段程式碼是模板程式碼,只需要修改AndroidInjector<T>中的泛型,改成需要注入的物件,也就是MainActivity
-
有了MainComponet,就需要將其注入到MainActivity之中
2.10之前,是通過這行程式碼
DaggerMainComponet.builder().build().inject(this);
實現的。現在Dagger2會幫我們自動實現注入,但是需要告訴Dagger2哪些Activity需要被注入。
新建ActivityBindingModule類:
@Module(subcomponents = {MainComponent.class}) public abstract class ActivityBindingModule { @Binds @IntoMap @ActivityKey(MainActivity.class) abstract AndroidInjector.Factory<? extends Activity> bindMainActivityInjectorFactory(MainComponent.Builder builder); }
可以看到,這個module裡面依賴了MainComponent,所以MainComponent需要使用
@SubComponet
註解,注入的程式碼也是通過MainComponent中的抽象方法 Builder 生成的。上面這段程式碼的作用:生成
Map<Activity.class, AndroidInjector.Factory<? extends Activity>>
的map,並將MainActivity的注入器放入其中。 -
建立AppComponent, 在modules中新增 AndroidSupportInjectionModule.class, ActivityBindModule.class,執行make project
@Component(modules = {AndroidSupportInjectionModule.class, ActivityBindModule.class}) public interface AppComponent extends AndroidInjector<DemoApp> { @Component.Builder abstract class Builder extends AndroidInjector.Builder<DemoApp>{ } }
-
make完成後會生成DaggerAppComponent類,在DemoApp中返回
@Override protected AndroidInjector<? extends DaggerApplication> applicationInjector() { return DaggerAppComponent.builder().create(this); }
-
最後在MainActivity中新增
AndroidInjection.inject(this);
public class MainActivity extends AppCompatActivity { @Inject Student student; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); AndroidInjection.inject(this); setContentView(R.layout.activity_main); Log.e(TAG, "student ---- " + student.toString()); } }
這一步也可以通過修改Acitivty的基類,省略
public class MainActivity extends DaggerActivity{ ... } //在DaggerActivity的原始碼中,可以看到內部已經我們添加了這行程式碼 @Beta public abstract class DaggerActivity extends Activity implements HasFragmentInjector { @Inject DispatchingAndroidInjector<Fragment> fragmentInjector; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { AndroidInjection.inject(this); super.onCreate(savedInstanceState); } @Override public AndroidInjector<Fragment> fragmentInjector() { return fragmentInjector; } }
上面就是完整的注入流程,所有的模板程式碼Dagger Android都已經幫我們處理好了,我們需要做的只是處理依賴注入關係。
大致的流程:

image
但是這麼多步驟,難免會產生錯誤,而且學習成本也增加了很多,好在Dagger2 2.11之後新增了 @ContributesAndroidInjector
簡化了注入過程(這個後面分析)。