首页 > 系统 > Android > 正文

Android Dagger2(一) 基本使用

2019-11-06 09:50:59
字体:
来源:转载
供稿:网友

欢迎转载,转载请标明出处: http://blog.csdn.net/johnny901114/article/details/58225116 本文出自:【余志强的博客】

Dagger2 是一个 依赖注入框架(DI), 对java开发有些了解的读者, 肯定熟悉这个概念, 好处就是解耦, 需要某个对象, 不需要自己通过new关键字去创建。

Dagger2 不是通过反射的方式去实现注入的,是通过生成代码的方式来达到注入效果的,在Android的很多开源框架中都是用到了代码生成工具(APT), 比如ButterKnife. 关于生成代码工具APT的使用可以参考我以前写的文章 :

Android开发之手把手教你写ButterKnife框架(一)

Android开发之手把手教你写ButterKnife框架(二)

Android开发之手把手教你写ButterKnife框架(三)

如何在项目中加入Dagger2框架

PRoject/build.gradle 文件中加入apt插件依赖, 如:

dependencies { classpath 'com.android.tools.build:gradle:2.2.3' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files }

然后在`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"}

如何使用Dagger2框架

先来了解下Dagger2的几个注解(Annotation)

@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类中会有如下两个方法来设置modulesdependencies配置的类型, DaggerAddMenuBalanceComponent通过Builder模式来设置属性 :

public Builder addMenuBalancePresenterModule( AddMenuBalancePresenterModule addMenuBalancePresenterModule) { this.addMenuBalancePresenterModule = Preconditions.checkNotNull(addMenuBalancePresenterModule); return this; } public Builder menuBalanceRepoComponent(MenuBalanceRepoComponent menuBalanceRepoComponent) { this.menuBalanceRepoComponent = Preconditions.checkNotNull(menuBalanceRepoComponent); return this; }

使用Dagger2框架来实现注入(MVP模式进行开发)

需求描述:

在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(二)源码分析-对象是如何被注入的


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表