欢迎转载,转载请标明出处: http://blog.csdn.net/johnny901114/article/details/58225116 本文出自:【余志强的博客】
Dagger2 是一个 依赖注入框架(DI), 对java开发有些了解的读者, 肯定熟悉这个概念, 好处就是解耦, 需要某个对象, 不需要自己通过new关键字去创建。
Dagger2 不是通过反射的方式去实现注入的,是通过生成代码的方式来达到注入效果的,在Android的很多开源框架中都是用到了代码生成工具(APT), 比如ButterKnife. 关于生成代码工具APT的使用可以参考我以前写的文章 :
Android开发之手把手教你写ButterKnife框架(一)
Android开发之手把手教你写ButterKnife框架(二)
Android开发之手把手教你写ButterKnife框架(三)
在 PRoject/build.gradle 文件中加入apt插件依赖, 如:
然后在`project/app/build.gradle 应用apt插件, 如:
apply plugin: 'com.android.application'apply plugin: 'com.neenbedankt.android-apt'最后加上dagger2库依赖 :
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) apt "com.google.dagger:dagger-compiler:2.2" compile "com.google.dagger:dagger:2.2"}@Module: 该注解要用在类上 , 该注解一般和@Provides一起使用, 主要是为@Component提供需要的对象
@Provides: 该注解用在方法上, 主要作用是提供依赖@Provides联合使用.
@Inject: 该注解要用在方法,构造方法和字段上.
1) 如果是用在字段上,表示需要注入该字段的对象;2) 如果用在构造方法上, 表示构造当前类对象通过此构造方法;3) 如果是用在方法上, 表示当前类对象构造完成后, 立马调用该方法.@Component: 该注解主要用在类上. 一般结合@Component的modules/dependencies属性一起使用. 如:
@Component(dependencies = MenuBalanceRepoComponent.class, modules = AddMenuBalancePresenterModule.class)public interface AddMenuBalanceComponent { void inject(AddMenuBalanceFragment fragment);}dependencies属性用于设置提供依赖的组件类(即加上了@Component注解的类)
modules属性用于设置依赖的模块类(即加上了@Modules注解的类)
Dagger2会自动生成Dagger+类名的Java类, 用于执行依赖注入操作. 如上面的类AddMenuBalanceComponent加上了@Component注解, Dagger2为我们会生成DaggerAddMenuBalanceComponent类.
在生成的类中会有相应的方法以供设置该属性配置的类型, 如生成的DaggerAddMenuBalanceComponent类中会有如下两个方法来设置modules和dependencies配置的类型, DaggerAddMenuBalanceComponent通过Builder模式来设置属性 :
需求描述:
在Activity/Fragment中依赖 Presenter , Presenter依赖 Model层, Model依赖远程数据源层. 也就是说这里有好几层依赖关系 :

下面贴出具体的代码, 因为是基于MVP分层的模式开发, 先把View层的接口贴出来:
IAddMenuBalanceView.java
public interface IAddMenuBalanceView { void addMenuBalanceSuccess(MenuBalance menuBalance); void addMenuBalanceFailure(String errorMsg);}Presenter接口IAddMenuBalancePresenter.java
public interface IAddMenuBalancePresenter { void addMenuBalance(); }
View层的Activity/Fragment :
AddMenuBalanceActivity.java
public class AddMenuBalanceActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_framelayout); getSupportFragmentManager().beginTransaction() .add(R.id.content, new AddMenuBalanceFragment()).commit(); }}AddMenuBalanceFragment.java
public class AddMenuBalanceFragment extends Fragment implements IAddMenuBalanceView { private ProgressDialog dialog; private TextView tvMenuBalanceList; @Inject AddMenuBalancePresenter presenter; //请求注入AddMenuBalancePresenter对象 @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); DaggerAddMenuBalanceComponent.builder() .menuBalanceRepoComponent(ComponentManager.getInstance().getMenuBalanceRepoComponent()) .addMenuBalancePresenterModule(new AddMenuBalancePresenterModule(this)) .build() .inject(this);//完成注入 } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.add_menu_balance_layout, container, false); tvMenuBalanceList = (TextView) view.findViewById(R.id.tv_menu_balance_list); view.findViewById(R.id.btn_add_menu_balance).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { showLoading(); presenter.addMenuBalance(); } }); return view; } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); } @Override public void addMenuBalanceSuccess(MenuBalance menuBalance) { hideLoading(); tvMenuBalanceList.append(menuBalance.getMenuId() + "--" + menuBalance.getMenuName() + "/n"); showToast("Added successfully"); } @Override public void addMenuBalanceFailure(String errorMsg) { hideLoading(); showToast(errorMsg); } void showLoading() { if (dialog == null) { dialog = new ProgressDialog(getActivity()); dialog.setMessage("请稍后..."); } dialog.show(); } void hideLoading() { if (dialog != null) { dialog.dismiss(); } } public void showToast(String message) { Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show(); }}AddMenuBalancePresenter.java
public class AddMenuBalancePresenter implements IAddMenuBalancePresenter { private final IAddMenuBalanceView mView; private final MenuBalanceRepository mMenuBalanceRepository; //如果需要AddMenuBalancePresenter对象的, 通过调用此构造方法 @Inject AddMenuBalancePresenter(IAddMenuBalanceView view, MenuBalanceRepository mMenuBalanceRepository) { this.mView = view; this.mMenuBalanceRepository = mMenuBalanceRepository; } @Override public void addMenuBalance() { mMenuBalanceRepository.addMenuBalance(new Callback<MenuBalance>() { @Override public void onSuccess(MenuBalance data) { mView.addMenuBalanceSuccess(data); } @Override public void onFailed(String errorMsg) { mView.addMenuBalanceFailure(errorMsg); } }); }}上面主要是View和Presenter层的代码, 现在通过Dagger2注解,把他们的依赖关系配置好 :
AddMenuBalanceComponent.java
@FragmentScoped@Component(dependencies = MenuBalanceRepoComponent.class, modules = AddMenuBalancePresenterModule.class)public interface AddMenuBalanceComponent { void inject(AddMenuBalanceFragment fragment);}AddMenuBalancePresenterModule.java
@Modulepublic class AddMenuBalancePresenterModule { private final IAddMenuBalanceView mView; public AddMenuBalancePresenterModule(IAddMenuBalanceView view) { mView = view; } @Provides IAddMenuBalanceView provideAddMenuBalanceView() { return mView; }}下面是数据层代码 :
/** * 远程数据源 如HTTP请求 */public class MenuBalanceRemoteSource implements IMenuBalanceSource { @Override public void addMenuBalance(final Callback<MenuBalance> callback) { //模拟网络请求 new AsyncTask<Void, Void, MenuBalance>() { @Override protected MenuBalance doInBackground(Void... params) { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); callback.onFailed(e.getMessage()); } return new MenuBalance("1001", "东坡肉"); } @Override protected void onPostExecute(MenuBalance menuBalance) { super.onPostExecute(menuBalance); callback.onSuccess(menuBalance); } }.execute(); }}MenuBalanceRepository.java Presenter需要的Model对象
public class MenuBalanceRepository implements IMenuBalanceSource { private final IMenuBalanceSource remoteSource; @Inject MenuBalanceRepository(IMenuBalanceSource remoteSource){ this.remoteSource = remoteSource; } @Override public void addMenuBalance(Callback<MenuBalance> callback) { remoteSource.addMenuBalance(callback); }}现在新建Model层的 Component和Module
MenuBalanceRepoComponent.java
@Singleton@Component(modules = {MenuBalanceRepoModule.class, ApplicationModule.class})public interface MenuBalanceRepoComponent { MenuBalanceRepository getMenuBalanceRepository();}MenuBalanceRepoModule.java
@Modulepublic class MenuBalanceRepoModule { @Singleton @Provides //@Remote IMenuBalanceSource provideRemoteDataSource() { return new MenuBalanceRemoteSource(); }}具体的项目源码可以到Github上去下载Dagger2 Sample
最终项目的运行效果:

如果你想知道Dagger2是如何实现依赖注入的, 可以查阅我的这篇博客 Android Dagger2(二)源码分析-对象是如何被注入的
新闻热点
疑难解答