初谈一Dagger2
离职的心绪,就如同立春这几天的天气,多了一点急躁,少了一份安宁...
上一个项目当时采用了 MVP
搭建框架,MVP
结合 Dagger2
,进一步解耦 P
层和 M
层模块。有关 MVP
的文章实在是太多了,如果你还不是很了解,还请科普下。Dagger2
是一个Android
依赖注入框架,由谷歌开发,最早的版本Dagger1
由Square
公司开发。依赖注入框架主要用于模块间解耦,提高代码的健壮性和可维护性。
本篇主要讲解 Dagger2
的使用。
依赖Dagger2
分为两步。
步骤一:
项目根目录build.gradle
文件中添加apt
插件:
dependencies {
classpath 'com.android.tools.build:gradle:2.2.3'
//引入apt插件
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
步骤二:
app
->build.gradle
文件添加如下代码:
apply plugin: 'com.android.application'
//添加如下代码,应用apt插件
apply plugin: 'com.neenbedankt.android-apt'
dependencies {
//添加依赖库
compile 'com.google.dagger:dagger:2.4'
apt 'com.google.dagger:dagger-compiler:2.4'
}
使用Dagger2
这里我将以登录模块
来讲解Dagger2
的使用。我们在使用MVP
模式中
Activity
持有presenter
的引用,同时presenter
也持有view
的引用,如果presenter
的构造函数改变,我们需要同时修改Activity
和presenter
代码,Activity
就和presenter
仅仅的耦合在一起了。那么我们怎样才能降低它们之间的耦合,以便后期的维护。感谢党为我们提供了Dagger2
依赖注入框架,那我们一起来看一看它在项目中是怎么使用的呢?
最终实现的效果图:
dag再来看看目录结构:
dag咳咳,大哥有你这么复杂吗?我经常一个Activity
就搞定了,还用你这么多类,花费多少时间啊?
如果你独立开发与维护这个项目还好点,如果是其他人来维护这个项目,可能就是一场灾难。若Activity
过于庞大臃肿,可能你都不知道从何下手?
优缺点就非常明显了,优点:易扩展易维护;缺点:代码量。
下面先来看看LoginActivity
的代码,文章结尾会附上源代码,本文贴代码的地方比较多,还请下载Demo
跑起来结合理解:
public class LoginActivity extends AppCompatActivity implements ILoginView {
//注入
@Inject
LoginPresenter mLoginPresenter;
EditText mEtUsername, mEtPassword;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mEtUsername = (EditText) findViewById(R.id.et_username);
mEtPassword = (EditText) findViewById(R.id.et_password);
DaggerLoginComponent.builder().loginModule(new LoginModule(this)).build().inject(this);
}
@Override
public void emptyData() {
Toast.makeText(this, getString(R.string.empty_data), Toast.LENGTH_SHORT).show();
}
@Override
public void loginFailed() {
Toast.makeText(this, getString(R.string.login_failed), Toast.LENGTH_SHORT).show();
}
@Override
public void loginSuccess() {
Toast.makeText(this, getString(R.string.login_success), Toast.LENGTH_SHORT).show();
}
public void login(View view) {
mLoginPresenter.login(mEtUsername.getText().toString(), mEtPassword.getText().toString());
}
}
在上述代码中可以看到LoginActivity
持有了LoginPresenter
的引用,并使用了@Inject
注解创建了该对象。注入的代码如下:
//注入
@Inject
LoginPresenter mLoginPresenter;
接下来看看LoginPresenter
类:
public class LoginPresenter {
LoginBiz mLoginBiz;
ILoginView mILoginView;
//此处使用了注解
@Inject
public LoginPresenter(ILoginView ILoginView) {
mILoginView = ILoginView;
mLoginBiz = LoginBiz.getInstance();
}
public void login(String username, String password) {
if (username.equals("") || password.equals("")) {
mILoginView.emptyData();
} else {
mLoginBiz.login(username, password, new ILoginBiz() {
@Override
public void loginSuccess() {
//如果是网络请求,请注意切换到主线程
mILoginView.loginSuccess();
}
@Override
public void loginFailed() {
mILoginView.loginFailed();
}
});
}
}
}
@Inject
标记 LoginPresenter
构造函数。 使用@Inject
还无法完成依赖注入,还需要如下两个新增类。
新增LoginModule
类:
//此处使用了注解
@Module
public class LoginModule {
private final ILoginView mILoginView;
public LoginModule(ILoginView ILoginView) {
mILoginView = ILoginView;
}
//此处使用了注解
@Provides
ILoginView provideLoginView() {
return mILoginView;
}
}
新增的LoginComponent
类:
//此处使用了注解
@Component(modules = LoginModule.class)
public interface LoginComponent {
public void inject(LoginActivity activity);
}
记得 rebuild
, LoginActivity
中通过:
DaggerLoginComponent.builder().loginModule(new LoginModule(this)).build().inject(this);
完成依赖注入。
你一定会有疑问,这里的@Inject
,@Module
,@Component
到底有什么用途。
-
@Inject 程序会将Dagger2会将带有此注解的变量或者构造方法参与到依赖注入当中,Dagger2会实例化这个对象。
-
@Module 带有该注解的类需要对外提供依赖,其实就是提供实例化需要的参数,Dagger2在实例化的过程中发现一些参数,Dagger2就会到该类中寻找带有@Provides注解的以provide开头的需找对应的参数。
-
@Component 带有该注解的接口或抽象类起到一个关联桥梁的作用,作用就是将带有@Inject的方法或对象和带有@Module的类进行关联,只有通过该接口或抽象类才可以在实例化的时候到带有 @Module中类中去寻找需要的参数,也就是依赖注入。
有关Dagger2
的简单使用就讲到这里。
我非常喜欢【平凡世界】里的一句话,送给大家。
我是一个平凡的人,但一个平凡的人,也可以过得不平凡。