dagger.android的简单使用
dagger.android
一、简介
dagger.android
是Dagger
的一个扩展,简单的说就是我们虽然降低了程序的耦合性,但是我们改变一个模块是,其中所对应的View中的代码仍然要改变,也就是说我们仍然要在Activity等中添加injet()
等代码,因此为了解决这个问题,就引入了dagger.android
,官方学习地址Github,本文就其基本使用与优化实战进行整理。
Dagger提供的基本类型:
DaggerActivity
DaggerFragment
DaggerService
DaggerIntentService
DaggerBroadcastReceiver
DaggerContentProvider
二、基本使用
添加依赖
compile 'com.google.dagger:dagger-android:2.19'
compile 'com.google.dagger:dagger-android-support:2.19'
annotationProcessor 'com.google.dagger:dagger-android-processor:2.19'
1、注入Activity
(1)创建MainComponent
继承AndroidInjector
,其抽象类Builder
由@Subcomponent.Builder
注解。
@Subcomponent(modules = {AndroidInjectionModule.class})
public interface MainComponent extends AndroidInjector<MainActivity> {
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder<MainActivity> {
}
}
(2)创建Student
类
public class Student {
private static final String TAG = "Student";
public void say(String name) {
Log.i(TAG, "say: 我是学生,我叫" + name);
}
}
(3) 创建MainModule
,定义子组件MainComponent
后,定义该子组件的MainModule
,通过将该Module注入
到AppComponentd
的modules
列表中,以便将MainActivitySubcomponent.Builder
添加到组件层次机构中。
@Module(subcomponents = MainComponent.class)
public abstract class MainModule {
@Binds
@ActivityKey(MainActivity.class)
@IntoMap
abstract AndroidInjector.Factory<? extends Activity>
bindYourActivityInjectorFactory(MainComponent.Builder builder);
//注意:必须添加@Singleton,否则报错
@Singleton
@Provides
static Student provideStudent(){
return new Student();
}
}
(4)为了使得我们的注解可以注入到Activity
、Fragment
、Service
、BroadcastReceiver
等中,我们通常把AndroidInjectionModule
放在ApplicationCoponent
中。
@Component(modules = AndroidInjectionModule.class)
public interface APPComponent {
void inject(App app);
}
(5)自定义Application
实现HasActivityInjector
并且通过@Inject
注入一个activityInjector()
方法返回的DispathcingAndroidInJector<Activity>
实例
public class App extends Application implements HasActivityInjector {
@Inject
DispatchingAndroidInjector<Activity> dispatchingActivityInjector;
@Override
public void onCreate() {
super.onCreate();
DaggerTodoComponent.create().inject(this);
}
@Override
public AndroidInjector<Activity> activityInjector() {
return dispatchingActivityInjector;
}
}
(6)在调用super.onCreate()
之前调用AndroidInjection.inject(this)
public class MainActivity extends AppCompatActivity {
@Inject
Student mStudent;
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
AndroidInjection.inject(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mStudent.say("小明");
}
}
输出:11-06 22:05:59.884 1149-1149/? I/Student: say: 我是学生,我叫小明
简单分析:AndroidInjection.inject()
从应用Application
中拿到一个DispatchingAndroidInjector<Activity>
并通过inject(Activity)
把Activity
传过去。这个DispatchingAndroidInjector
会查找Activity
类的AndroidInjector.Factory(YourActivitySubcomponent.Builder)
,构建AndroidInjector(YourActivitySubcomponent)
,然后把Activity
传给inject(YourActivity)
,这样就自动完成了注入。
2、注入Fragment
注入Fragment
和Activity
使用基本相同,下面列出不同:
- 将所有
Activity
替换成Fragment
- 将
@ActivityKey
替换成@FragmentKey
- 将
HasActivityInjector
替换成HasFragmentInjector
- 要在
Fragment
要通过onAttach()
方法注入。 -
Fragment
的Module
的添加位置,与Activity
定义的Module
添加不同,其取决于Fragment
内部所需要的其他绑定的依赖注入;
这里列出官网的一些代码:
public class YourActivity extends Activity implements HasFragmentInjector {
@Inject
DispatchingAndroidInjector<Fragment> fragmentInjector;
@Override
public void onCreate(Bundle savedInstanceState) {
AndroidInjection.inject(this);
super.onCreate(savedInstanceState);
}
@Override
public AndroidInjector<Fragment> fragmentInjector() {
return fragmentInjector;
}
}
public class YourFragment extends Fragment {
@Inject
SomeDependency someDep;
@Override
public void onAttach(Activity activity) {
AndroidInjection.inject(this);
super.onAttach(activity);
}
}
@Subcomponent(modules = ...)
public interface YourFragmentSubcomponent extends AndroidInjector<YourFragment> {
@Subcomponent.Builder
public abstract class Builder extends AndroidInjector.Builder<YourFragment> {}
}
@Module(subcomponents = YourFragmentSubcomponent.class)
abstract class YourFragmentModule {
@Binds
@IntoMap
@FragmentKey(YourFragment.class)
abstract AndroidInjector.Factory<? extends Fragment>
bindYourFragmentInjectorFactory(YourFragmentSubcomponent.Builder builder);
}
@Subcomponent(modules = { YourFragmentModule.class, ... }
public interface YourActivityOrYourApplicationComponent { ... }
三、优化
通过上面的学习,我们可以看出dagger.android
的使用,并没有使dagger
使用更加方便,因此我们需要对其使用进行优化,这就用到@ContributesAndroidInjector
了。
@ContributesAndroidInjector
可以返回对应activity
,因此使用@ContributesAndroidInjector
对其进行注解,并指定要安装到子组件中的模块。
@ActivityScope
@ContributesAndroidInjector(modules = { /* modules to install into the subcomponent */ })
abstract YourActivity contributeYourActivityInjector();
使用方法:
(1)创建Student
类
public class Student {
private static final String TAG = "Student";
public void say(String name) {
Log.i(TAG, "say: 我是学生,我叫" + name);
}
}
(2)创建MainActivityModule
,用以给MainActivity
提供各种对象,如:Student
@Module
public class MainActivityModule {
@Provides
Student provideStudent(){
return new Student();
}
}
(3)创建BaseActivity
,用以返回所有的对应activity
@Module
public abstract class BaseActivityModule {
@ContributesAndroidInjector(modules = {MainActivityModule.class})
abstract MainActivity bindMainActivity();
}
(4)为了使得我们的注解可以注入到Activity
、Fragment
、Service
、BroadcastReceiver
等中,我们通常把AndroidInjectionModule
放在ApplicationCoponent
中。
@Component(modules = {AndroidInjectionModule.class,
AndroidSupportInjectionModule.class,
BaseActivityModule.class})
public interface AppComponent extends AndroidInjector<App> {
@Component.Builder
interface Builder{
@BindsInstance
Builder app(App app);
AppComponent build();
}
void inject(App app);
}
(5)自定义Application
继承DaggerApplication
,使得Application
和AppComponent
绑定。
public class App extends DaggerApplication {
@Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
AppComponent appComponent = DaggerAppComponent.builder().app(this).build();
return appComponent;
}
}
(6)输出Student
public class MainActivity extends DaggerAppCompatActivity {
@Inject
Student mStudent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mStudent.say("小明");
}
}
输出:11-09 22:01:48.365 1152-1152/? I/Student: say: 我是学生,我叫小明