Dagger-android 量身定做的Dagger

目录

0. 为什么定制?

1. 2.10版本复杂的方式

1.0 导包

1.1 依赖创建

1.2 依赖注入

1.3 让这一切被Dagger所知晓

1.4 源码看了一下 结合 生成的代码

2. 2.11版本@ContributesAndroidInjector


0. 为什么定制?

从 Dagger2入门 了解到,Dagger2的一个坑就是:

Component inject(container c) 容器必须传入与你实际调用inject相同的类。也就是说不能c传入BaseActivity,实际调用在XActivity。

也就是说如果我们用到了Dagger2,就必须每个Activity中去写一句如下的inject(this),肯定是不可能这么low的。

DaggerUserComponent.create().inject(this);

Dagger提供了两种方式解决:

  • 2.10版本提供了相对复杂的解决方式
  • 2.11版本@ContributesAndroidInjector简化流程

如果为了使用,直接使用ContributesAndroidInjector注解方式即可。

 

1. 2.10版本复杂的方式

此种方式主要是为了大致了解实现的逻辑,不具备实际开发用处。

 

1.0 导包

在Dagger的基础上新增Android定制支持。

    // dagger2
    implementation 'com.google.dagger:dagger:2.19'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.19'
    // dagger android
    implementation 'com.google.dagger:dagger-android:2.19'
    implementation 'com.google.dagger:dagger-android-support:2.19'
    annotationProcessor 'com.google.dagger:dagger-android-processor:2.19'

1.1 依赖创建

和之前一样,没啥说的。

package com.fengzhen.anddagger.old;

public class User {
    private String name;
    private String password;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

提供一个用户名为“小明”的Module

package com.fengzhen.anddagger.old;

import dagger.Module;
import dagger.Provides;

@Module
public class UserModule {

    @Provides
    User provideLoginXM() {
        User login = new User();
        login.setName("小明");
        login.setPassword("123123");
        return login;
    }
}

 

1.2 依赖注入

这里就和之前不一样了,不再需要苦哈哈的去写inject(),只需要在BaseActivity继承Dagger-android提供的DaggerAppCompatActivity就可以了。

实际注入位置:

public class SecondActivity extends BaseActivity {

    @Inject
    User mLoginUser;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

//        DaggerUserComponent.create().inject(this);

        Log.i("fengzhen1", "onCreate: " + mLoginUser.getName());
    }
}

BaseActivity也啥都没写:

package com.fengzhen.anddagger;

import android.os.Bundle;
import android.support.annotation.Nullable;

import dagger.android.support.DaggerAppCompatActivity;

/**
 * 创建时间:2018/12/12
 * 版   本:v1.0.0
 * 作   者:fengzhen
 * <p>
 * 功能描述:什么都不用写,只需要继承 DaggerAppCompatActivity 就好了
 */
public class BaseActivity extends DaggerAppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
}

 

1.3 让这一切被Dagger所知晓

这也是做出改动的一个环节。还是1 2 3一步一步先实现功能。

 

1. 创建AppComponent。管理所有的子模块的Module。这里的BuildersModule相当于一个子模块;AndroidSupportInjectionModule 是Dagger-android提供的如四大组件、Fragment等的底层注入,后面简单看看。

package com.fengzhen.anddagger;

import javax.inject.Singleton;

import dagger.Component;
import dagger.android.AndroidInjector;
import dagger.android.support.AndroidSupportInjectionModule;

@Singleton
@Component(modules = {
        BuildersModule.class,
        AndroidSupportInjectionModule.class})
public interface AppComponent extends AndroidInjector<MyApplication> {

    @Component.Builder
    abstract class Builder extends AndroidInjector.Builder<MyApplication> {
    }
}

 

2. 子模块BuildersModule,绑定具体的UserComponent。(之前/之后 是2.11对比2.10 不用看)

package com.fengzhen.anddagger;

import android.app.Activity;

import com.fengzhen.anddagger.old.SecondActivity;
import com.fengzhen.anddagger.old.UserComponent;
import com.fengzhen.anddagger.old.UserModule;

import dagger.Binds;
import dagger.Module;
import dagger.android.ActivityKey;
import dagger.android.AndroidInjector;
import dagger.android.ContributesAndroidInjector;
import dagger.multibindings.IntoMap;

// ContributesAndroidInjector之前
@Module(subcomponents = UserComponent.class)
public abstract class BuildersModule {

    @Binds
    @IntoMap
    @ActivityKey(SecondActivity.class)
    abstract AndroidInjector.Factory<? extends Activity> bindSecondActivityInjectorFactory(
            UserComponent.Builder builder
    );
}

// ContributesAndroidInjector之后
//@Module
//public abstract class BuildersModule {
//    @ContributesAndroidInjector(modules = UserModule.class)
//    abstract SecondActivity secondActivityInjector();
//}

 

3. UserComponent主要是继承AndroidInjector,并传入Container泛型具体容器。(befor/after 是Dagger2基础和Dagger-android对比,不用看)

package com.fengzhen.anddagger.old;

import dagger.Subcomponent;
import dagger.android.AndroidInjector;

//// befor
//@Component(modules = UserModule.class)
//public interface UserComponent {
//    void inject(SecondActivity secondActivity);
//}

/**
 * 主要申明注入到的具体位置
 */
// after
@Subcomponent(modules = UserModule.class)
public interface UserComponent extends AndroidInjector<SecondActivity> {

    @Subcomponent.Builder
    abstract class Builder extends AndroidInjector.Builder<SecondActivity> {
    }
}

 

4.创建MyApplication并且继承DaggerApplication,将整个逻辑链接起来,别忘了manifests进行注册。

package com.fengzhen.anddagger;

import dagger.android.AndroidInjector;
import dagger.android.DaggerApplication;

public class MyApplication extends DaggerApplication {
    @Override
    protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
        return DaggerAppComponent.builder().create(this);
    }
}

如此,整个注入就完成。不再需要每个Container去inject,简直不要太爽。

 

1.4 源码看了一下 结合 生成的代码

1. DaggerAppCompatActivity主要就调用了一句代码 AndroidInjection.inject(this),然后与AppComponet关联,继而关联整个注入链。

2. MembersInjector<T> 通过泛型injectMembers()方法获得具体的——UserComponent传入的泛型SecondActivity——Container类型。实现在BaseActivity中进行具体的容器注入。

3. DaggerApplication实现HasActivityInjector接口,activityInjector()方法获取到全局的Application级别的AndroidInjector注入器。之后DaggerAppCompatActivity中inject(this)传入具体的容器注入。

4.AndroidSupportInjectionModule以及AndroidInjectionModule实现了具体的容器级别的注入,当然应用层级无法感知。

 

2. 2.11版本@ContributesAndroidInjector

BuildersModule改一下就可以了,而且UserComponent可以不写,可以不写。其他不变~~

package com.fengzhen.anddagger;

import com.fengzhen.anddagger.old.SecondActivity;
import com.fengzhen.anddagger.old.UserModule;

import dagger.Module;
import dagger.android.ContributesAndroidInjector;

// ContributesAndroidInjector之前
//@Module(subcomponents = UserComponent.class)
//public abstract class BuildersModule {
//
//    @Binds
//    @IntoMap
//    @ActivityKey(SecondActivity.class)
//    abstract AndroidInjector.Factory<? extends Activity> bindSecondActivityInjectorFactory(
//            UserComponent.Builder builder
//    );
//}

// ContributesAndroidInjector之后
@Module
public abstract class BuildersModule {
    @ContributesAndroidInjector(modules = UserModule.class)
    abstract SecondActivity secondActivityInjector();
}

纸上得来终觉浅,以后实际项目中用到了的时候在研究补充吧,比如侵入性太高的问题也还不知道对实际项目有什么影响。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章