Dagger2概念
注入的概念
依賴注入:就是目標類(目標類需要進行依賴初始化的類,下面都會用目標類一詞來指代)中所依賴的其他的類的初始化過程,不是通過手動編碼的方式創建,而是通過技術手段可以把其他的類的已經初始化好的實例自動注入到目標類中。
Inject
我們可以用註解(Annotation)來標註目標類中所依賴的其他類,同樣用註解來標註所依賴的其他類的構造函數,那註解的名字就叫Inject
class A{
@Inject
B b;
}
class B{
@Inject
B(){
}
}
Component
通俗點來將component就是註解類和被註解類之間的橋樑,他通常是一個接口。註解類也就是上面B類中的構造函數,被註解類也就是上面A類中的得到的B類的實例。
Moudle
現在有個新問題:項目中使用到了第三方的類庫,第三方類庫又不能修改,所以根本不可能把Inject註解加入這些類中,這時我們的Inject就失效了。
@Module
public class ModuleClass{
//A是第三方類庫中的一個類
A provideA(){
return A();
}
}
Module其實是一個簡單工廠模式,Module裏面的方法基本都是創建類實例的方法。也即是說Moudle是Component的提供者。
Provides
那Moudle和Component之間怎麼建立聯繫呢,那就要通過Provides了
Module中的創建類實例方法用Provides進行標註,Component在搜索到目標類中用Inject註解標註的屬性後,Component就會去Module中去查找用Provides標註的對應的創建類實例方法,這樣就可以解決第三方類庫用dagger2實現依賴注入了。
整個注入流程
- 如果有第三方庫的使用,首先要建立Moudle
- 然根據Moudle來建立Component
- 通過Inject來進行註解,一個是註解提供類構造函數,一個是註解目標類的實例,這樣就建立了聯繫
簡單例子
引入資源
在project的build.gradle中
classpath 'com.android.tools.build:gradle:2.1.2'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
在app/build.gradle中
dependencies {
...
// Add Dagger dependencies,2017.04.26
compile 'com.google.dagger:dagger:2.11-rc1'
annotationProcessor 'com.google.dagger:dagger-compiler:2.11-rc1'
}
IPresenter和IView
public interface IView {
/**
* 更新UI
* @param data
*/
void updateUi(String data);
}
public interface IPresenter {
/**
* 加載數據
*/
void loadData();
}
MyPresenter實現IPresenter接口
public class MyPresenter implements IPresenter{
private IView mainView;
public MyPresenter(IView view){
mainView = view;
}
@Override
public void loadData() {
mainView.updateUi("Mvp Update UI "+System.currentTimeMillis());
}
}
MyModule類
注意這裏的MyPresenter的創建需要依賴View,而這個View是通過Moudle的構造方法傳過來的。
@Module
public class MyModule {
private IView mainView;
public MyModule(IView mainView){
this.mainView = mainView;
}
@Provides
public MyPresenter provideMyPresenter(){
return new MyPresenter(mainView);
}
}
AppComponent類
派生到我的代碼片
@Component(modules = MyModule.class)
public interface AppComponent {
void inject(MainActivity activity);
}
MainActivity
public class MainActivity extends AppCompatActivity implements IView, View.OnClickListener {
@Bind(R.id.result)
TextView tv_result;
@Bind(R.id.btn_update)
Button btn_update;
@Inject
MyPresenter myPresenter; //獲取依賴的對象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
btn_update.setOnClickListener(this);
DaggerAppComponent.builder()
.myModule(new MyModule(this))
.build()
.inject(this); //注入
}
@Override
public void updateUi(String data) {
tv_result.setText(data);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_update:
myPresenter.loadData();
break;
}
}
}
實現效果
UI頁面中是一個TextView和一個Button,當我們點擊Button的時候就會改變TextView的值。
項目的步驟如下
- 首先建立moudle,moudle的初始話需要傳入一個View,也就是我們這裏的Activity,moudle初始化一個presenter並通過provide提供給component
- 初始化component,這裏需要依賴moudle
- make我們的project並進行注入的操作
- 然後就可以調用注入的presenter進行操作了