依賴注入
面向?qū)ο缶幊痰囊环N設(shè)計(jì)模式扑媚,目的是為了降低程序中類與類之間的依賴引起的耦合霉祸。
在Java中客们,依賴注入有
- 通過(guò)接口注入
- 通過(guò)set方法注入
- 通過(guò)構(gòu)造方法注入
- 通過(guò)注解注入
Dagger2
為什么要用Dagger
讓你不需要初始化對(duì)象。也就是說(shuō)任何對(duì)象聲明完了就能直接用缭裆。另外一種說(shuō)法:使用類和被依賴的對(duì)象構(gòu)造分開,這樣如果我們需要改變被依賴類的構(gòu)造方法,不必改動(dòng)每一個(gè)使用類寿烟。
降低大型項(xiàng)目的耦合度
簡(jiǎn)單的示例
比如現(xiàn)在我們要在RecycleView中顯示一系列數(shù)據(jù)澈驼,那么我們需要在Activity中引用RecyclerViewAdapter。
最原始的構(gòu)造方法注入的寫法
MainActivity
public class MainActivity extends AppCompatActivity {
List<String> list = new ArrayList<>();
RecyclerView recyclerView;
ARecyclerViewAdapter aRecyclerViewAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.rv);
for (int i = 0; i < 30; i++) {
list.add("item" + i);
}
recyclerView.setLayoutManager(new LinearLayoutManager(this));
//實(shí)例化并傳入list數(shù)據(jù)
aRecyclerViewAdapter = new ARecyclerViewAdapter(list);
recyclerView.setAdapter(aRecyclerViewAdapter);
}
}
adapter
public class ARecyclerViewAdapter extends RecyclerView.Adapter<ARecyclerViewAdapter.AViewHolder>{
private List<String> list ;
public ARecyclerViewAdapter(List<String> list) {
this.list = list;
}
@Override
public AViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_item, parent, false);
return new AViewHolder(view);
}
@Override
public void onBindViewHolder(AViewHolder holder, int position) {
holder.textView.setText(list.get(position));
}
@Override
public int getItemCount() {
return list.size();
}
public class AViewHolder extends RecyclerView.ViewHolder{
TextView textView;
public AViewHolder(View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.tv);
}
}
}
現(xiàn)在用Dagger2來(lái)改造筛武,總體來(lái)說(shuō)就是4步:
- 1 在Adapter構(gòu)造器中加入@Inject注解
- 2 構(gòu)建 Module
- 3 構(gòu)建 Component
- 4 完成依賴注入
1 MainActivity中
public class MainActivity extends AppCompatActivity {
List<String> list = new ArrayList<>();
RecyclerView recyclerView;
//1 這里對(duì)注入類聲明并用注解@Inject標(biāo)記
@Inject
ARecyclerViewAdapter aRecyclerViewAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.rv);
for (int i = 0; i < 30; i++) {
list.add("item" + i);
}
// aRecyclerViewAdapter = new ARecyclerViewAdapter(list);
....
....
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(aRecyclerViewAdapter);
}
}
在ARecyclerViewAdapter中
@Inject
public ARecyclerViewAdapter(List<String> list) {
this.list = list;
}
其實(shí)就是在倆個(gè)地方加了Inject注解
2 寫Module
@Module
public class ListModule {
List<String> list;
//引入數(shù)據(jù)
public ListModule(List<String> list) {
this.list = list;
}
//提供數(shù)據(jù)
@Provides
@ActivityScope
List<String> provideList(){
return list;
}
}
原來(lái)的adapter的構(gòu)造方法是
public ARecyclerViewAdapter(List<String> list) {
this.list = list;
}
這里這個(gè)list要從MainActivity中注入到adapter的缝其,用module來(lái)提供數(shù)據(jù)挎塌,上面的provideList()方法就是提供數(shù)據(jù)的,用了Provides
注解内边。這里adapter只有一個(gè)參數(shù)榴都,如果有多個(gè)參數(shù),同理都在Module中用provide開頭方法提供漠其。
@ActivityScope 是一個(gè)自定義的范圍注解嘴高,作用是允許對(duì)象被記錄在正確的組件中,當(dāng)然這些對(duì)象的生命周期應(yīng)該遵循 Activity 的生命周期
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import javax.inject.Scope;
@Scope
@Retention(RUNTIME)
public @interface ActivityScope {
}
3 Component
負(fù)責(zé)注入依賴
@ActivityScope
@Component(modules = {ListModule.class})
public interface ListComponent {
void inject(MainActivity mainActivity);
}
這里void inject(MainActivity mainActivity)
要注意這里必須是真正消耗依賴的類型 MainActivity
4 在MainActivity中
onCreate方法中
DaggerListComponent.builder().listModule(new ListModule(list)).build().inject(this);
這樣就完了
為什么用Dagger
我們?yōu)槭裁匆袲agger2,MVP以及Rxjava引入項(xiàng)目中?
Dagger——Android上的依賴注入框架
參考資料
Dagger 2: Step To Step
Dagger2從入門到放棄再到恍然大悟
Using Dagger2 in Android
Dagger是什么和我們?cè)趺赐ㄟ^(guò)使用它獲得收獲
end