1,这一篇博客是和大家一起来封装我们最后的Dagger2,其实之前也写过关于简单的Dagger2,这里是地址,完全没了解的同学可以先去看一下这篇,感谢很多小伙伴一直在耐心的等待这一篇
2,Dagger2可以说是些技术中最难上手的,不过把主要的四个注解理解到位了,基本上就可以用了:
1
2
3
4
5
6
7
|
@Inject
Inject主要有两个作用,一个是使用在构造函数上,通过标记构造函数让Dagger2来使用(Dagger2通过Inject标记可以在需要这个类实例的时候来找到这个构造函数并把相关实例
new
出来)从而提供依赖,另一个作用就是标记在需要依赖的变量让Dagger2为其提供依赖。
@Provide
用Provide来标注一个方法,该方法可以在需要提供依赖时被调用,从而把预先提供好的对象当做依赖给标注了
@Injection
的变量赋值。provide主要用于标注Module里的方法
@Module
用Module标注的类是专门用来提供依赖的。有的人可能有些疑惑,看了上面的
@Inject
,需要在构造函数上标记才能提供依赖,那么如果我们需要提供的类构造函数无法修改怎么办,比如一些jar包里的类,我们无法修改源码。这时候就需要使用Module了。Module可以给不能修改源码的类提供依赖,当然,能用Inject标注的通过Module也可以提供依赖
@Component
Component一般用来标注接口,被标注了Component的接口在编译时会产生相应的类的实例来作为提供依赖方和需要依赖方之间的桥梁,把相关依赖注入到其中。
|
下面你这张图片很相像的概括了上面四个标签的作用
还有两个常见的标签是@Scope和@Qulifier ,@Scope标签你可以将它理解成单例标记,@Qulifier可以简单的理解成区分需要的对象有两个或者两个以上构造方法(主要用于区分),
首先我们用一个简单的场景来引入吧,现在我们项目使用MVP架构, 而引入Dagger2的主要目的是解决我们在Activity中new Presenter对象,先看一下我们在引用之前代码是怎么样的吧
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
package
com.qianmo.myview2;
import
android.support.v7.app.AppCompatActivity;
import
android.os.Bundle;
import
com.qianmo.myview2.presenter.HiPresenterImpl;
public
class
MainActivity
extends
AppCompatActivity {
private
HiPresenterImpl hiPresenter;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//直接new对象
hiPresenter =
new
HiPresenterImpl();
}
}
|
这时候引用Dagger2,再看看我们的代码
MainActiivty.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
package
com.qianmo.myview2;
import
android.support.v7.app.AppCompatActivity;
import
android.os.Bundle;
import
com.qianmo.myview2.presenter.HiPresenterImpl;
import
javax.inject.Inject;
public
class
MainActivity
extends
AppCompatActivity {
@Inject
private
HiPresenterImpl hiPresenter;
//这里改变了
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
|
Presenter.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
package
com.qianmo.myview2.presenter;
import
com.qianmo.myview2.contract.HiContract;
import
javax.inject.Inject;
/**
* Created by MVPHelper on 2016/10/20
*/
public
class
HiPresenterImpl
implements
HiContract.Presenter{
@Inject
public
HiPresenterImpl(){
}
}
|
光上面的这两个标注还不够,我们还要创建对应的Module和Component
MainModule.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
package
com.qianmo.myview2.di.module;
import
com.qianmo.myview2.presenter.HiPresenterImpl;
import
dagger.Module;
import
dagger.Provides;
/**
* Created by wangjitao on 2017/3/9 0009.
* E-Mail:543441727@qq.com
*/
@Module
public
class
MainModule {
@Provides
HiPresenterImpl provideHiPresenterImpl() {
return
new
HiPresenterImpl();
}
}
|
MainComponent.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
package
com.qianmo.myview2;
import
android.support.v7.app.AppCompatActivity;
import
android.os.Bundle;
import
com.qianmo.myview2.di.component.DaggerMainComponent;
import
com.qianmo.myview2.di.module.MainModule;
import
com.qianmo.myview2.presenter.HiPresenterImpl;
import
javax.inject.Inject;
public
class
MainActivity
extends
AppCompatActivity {
@Inject
private
HiPresenterImpl hiPresenter;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMainComponent.builder().mainModule(
new
MainModule()).build().inject(
this
);
hiPresenter.say();
}
}
|
这样我们就简单的使用了,再来简单的分析一下流程 :被 @Inject 注解的代码存在某种联系,当代码执行到 @Inject 的时候程序会自动进入到这个类的构造方法中,如果正巧这个构造方法也被 @Inject 修饰了,那么系统就会帮我们自动创建对象。
3,封装
由上面的项目我们进行过度,但我们封装的时候,主要是要在activity和fragment来持有Presenter对象,先来封装Activity,这是目录
先看一下我们之前的presenter的创建,在BaseActivity中添加抽象方法,在Mainactivity中重写方法再new对象
先创建Application的Module,Application的话主要是提供上下文环境,而appliacation中的component,只是提供Context展示方法get方法
AppModule.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
package
com.qianmo.mvpproject.di.module;
import
com.qianmo.mvpproject.App;
import
com.qianmo.mvpproject.di.ContextLife;
import
javax.inject.Singleton;
import
dagger.Module;
import
dagger.Provides;
/**
* Created by wwangjitao on 16/8/7.
*/
@Module
public
class
AppModule {
private
final
App application;
public
AppModule(App application) {
this
.application = application;
}
@Provides
@Singleton
@ContextLife
(
"Application"
)
App provideApplicationContext() {
return
application;
}
}
|
AppComponent.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
package
com.qianmo.mvpproject.di.component;
import
com.qianmo.mvpproject.App;
import
javax.inject.Singleton;
import
com.qianmo.mvpproject.di.ContextLife;
import
com.qianmo.mvpproject.di.module.AppModule;
import
dagger.Component;
/**
* Created by wangjitao on 16/8/7.
*/
@Singleton
@Component
(modules = AppModule.
class
)
public
interface
AppComponent {
@ContextLife
(
"Application"
)
App getContext();
// 提供App的Context
}
|
而Activity的Module主要是提供Activity和上下文Context对象,对应的Activity的component主要是将提供的对象注入到需要它的地方
ActivityModule.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
package
com.qianmo.mvpproject.di.module;
import
android.app.Activity;
import
android.content.Context;
import
com.qianmo.mvpproject.base.BaseRxPresenter;
import
com.qianmo.mvpproject.di.ActivityScope;
import
dagger.Module;
import
dagger.Provides;
/**
* Created by codeest on 16/8/7.
*/
@Module
public
class
ActivityModule {
private
Activity mActivity;
public
ActivityModule(Activity activity) {
this
.mActivity = activity;
}
@Provides
@ActivityScope
public
Activity provideActivity() {
return
mActivity;
}
@Provides
public
Context provideContext() {
return
mActivity;
}
}
|
ActivityComponent.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
package
com.qianmo.mvpproject.di.component;
import
android.app.Activity;
import
com.qianmo.mvpproject.di.ActivityScope;
import
com.qianmo.mvpproject.di.module.ActivityModule;
import
com.qianmo.mvpproject.ui.activity.CheckVersionActivity;
import
dagger.Component;
/**
* Created by codeest on 16/8/7.
*/
@ActivityScope
@Component
(dependencies = AppComponent.
class
, modules = ActivityModule.
class
)
public
interface
ActivityComponent {
Activity getActivity();
void
inject(CheckVersionActivity welcomeActivity);
}
|
再在BaseActivity中去调用
BaseActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
package
com.qianmo.mvpproject.base;
import
android.app.Activity;
import
android.os.Bundle;
import
android.support.annotation.Nullable;
import
android.support.v7.app.AppCompatActivity;
import
android.support.v7.widget.Toolbar;
import
javax.inject.Inject;
import
com.qianmo.mvpproject.App;
import
com.qianmo.mvpproject.R;
import
com.qianmo.mvpproject.di.component.ActivityComponent;
import
com.qianmo.mvpproject.di.component.DaggerActivityComponent;
import
com.qianmo.mvpproject.di.module.ActivityModule;
import
butterknife.ButterKnife;
import
butterknife.Unbinder;
/**
* Created by wangjitao on 2016/11/8 0008.
* 基类Activity的封装
* 一般使用mvp模式的话会在BaseActivity中进行P和V的初始化绑定
*/
public
abstract
class
BaseActivity<T
extends
BasePresenter>
extends
AppCompatActivity
implements
BaseView {
//这里添加了注入
@Inject
protected
T mPresenter;
.......省略
protected
void
onCreate(
@Nullable
Bundle savedInstanceState) {
.......省略
super
.onCreate(savedInstanceState);
setContentView(getLayout());
//这里添加了注入的调用
initInject();
if
(mPresenter !=
null
)
mPresenter.attachView(
this
);
}
//添加调用方法
protected
ActivityComponent getActivityComponent(){
return
DaggerActivityComponent.builder()
.appComponent(App.getAppComponent())
.activityModule(getActivityModule())
.build();
}
protected
ActivityModule getActivityModule(){
return
new
ActivityModule(
this
);
}
}
|
ok,这样我们就封装了,同理Fragment,这里就不废话写了,下面把github地址贴上,后面打算这些东西写一个展示类的app,又要到处找接口了,See You Next Time !