Dagger2

Dagger2 并不是 Jetpack 中的一员。

既然我们说了 Dagger2 是一个依赖注入框架,那么还是需要了解下,什么是依赖注入,为什么要用依赖注入。
类通常需要引用其他类。例如,Car 类可能需要引用 Engine 类,像 Engine 这种被依赖的类称为依赖项。一个类可以通过三种方式获取依赖项的对象:

    类构造其所需的依赖项。例如在 Car 类中创建并初始化自己所需的 Engine 实例
    从其他地方抓取。如 Android Context 中的 getSystemService()
    以参数形式提供。应用可以在构造一个类时提供这些依赖项,或者将这些依赖项传入需要依赖项的函数,如在创建 Car 对象时将 Engine 对象通过 Car 的构造方法或 setter 方法传入

第三种方式就是依赖注入(DI,Dependency Injection)。使用依赖注入时,一个类不必再自己获取依赖项,而是由外部提供。比如说:


    /**
    * 代码示例1:
    * 在 Car 类内部,由 Car 自己创建依赖项 Engine 的实例
    */
    class Car {
    
        private Engine engine = new Engine();
    
        public void start() {
            engine.start();
        }
    }
    
    class MyApp {
        public static void main(String[] args) {
            Car car = new Car();
            car.start();
        }
    }

按照上述代码,Car 对 Engine 是一个强依赖关系,不利于扩展和测试,在使用依赖注入的方式后:


    /**
    * 示例代码2:
    * 使用依赖注入方式创建对象
    */
    class Car {
    
        private final Engine engine;
    
        // 依赖注入方式一:构造方法注入
        public Car(Engine engine) {
            this.engine = engine;
        }
    
        public void start() {
            engine.start();
        }
    
        // 依赖注入方式二:字段(setter方法)注入
        public void setEngine(Engine engine) {
            this.engine = engine;
        }
    }
    
    class MyApp {
        public static void main(String[] args) {
            // 依赖注入框架实际上干的就是创建对象并交给需要它的类这件事
            Engine engine = new Engine();
            Car car = new Car(engine);
            car.start();
        }
    }


实现了控制反转(IoC,Inversion of Control),将原本的正向控制,即在 Car 类中主动去获取/创建所需要的外部资源 Engine,改成了被动等待外部获取到一个 Engine 的实例然后注入到 Car 中。这样做的好处有:

    重用类以及分离依赖项:更容易换掉依赖项的实现。由于控制反转,代码重用得以改进,并且类不再控制其依赖项的创建方式,而是支持任何配置
    易于重构:依赖项在创建对象时或编译时可以进行检查,而不是作为实现详情隐藏
    易于测试:类不管理其依赖项,因此在测试时,可以传入不同的实现以测试不同用例

Dagger2 在编译时会自动生成代码,这些生成的代码与原本需要手动编写的注入代码类似,这样就无需我们再手动编写冗长乏味又容易出错的异步代码了。它会完成以下工作:

    构建并验证依赖关系图,确保每个对象的依赖关系都能满足且图中不存在依赖循环,简言之就是根据依赖关系生成有向无环图
    为有向无环图中的类创建工厂以满足依赖关系,并通过该工厂生产实际对象
    通过作用域管理对象的生命周期,并且决定是重复使用依赖项还是创建新的实例
    为特定流程创建容器,这样在对象的生命周期结束后,可以及时释放内存中不再需要的对象,提升性能
    
Dagger2中注解
注解 描述
@Inject 指示 Dagger 如何实例化一个对象,可以作用在构造方法或需要注入的字段上
1是在需要依赖的类(下面这样的类都会称为目标类)中标记成员变量告诉Dagger这个类型的变量需要一个实例对象。
2是标记类中的构造方法,告诉Dagger我可以提供这种类型的依赖实例。
@Provides 指示 Dagger 以非构造方法的方式实例化一个对象
对方法进行注解,都是有返回类型的。用来告诉Dagger我们想如何创建并提供该类型的依赖实例(一般会在方法中new出实例)。用@Provide标记的方法,谷歌推荐采用provide为前缀
@Module 指示 Dagger 以非构造方法的方式实例化一个对象
@Module这个注解用来标记类(一般类名以Module结尾)。Module主要的作用是用来集中管理@Provide标记的方法。我们定义一个被@Module注解的类,Dagger就会知道在哪里找到依赖来满足创建类的实例。modules的一个重要特征是被设计成区块并可以组合在一起。(例如可以在App中看到多个组合在一起的modules)
@Singleton
@Scope
作用域,用来标记依赖项的生命周期(作用域),还有一个作用是标记单例
Dagger2通过自定义注解来限定作用域。这是一个非常强大的功能,所有的对象都不再需要知道怎么管理它自己的实例。Dagger2中有一个默认的作用域注解@Singleton,通常在Android中用来标记在App整个生命周期内存活的实例。也可以自定义一个@PerActivity注解,用来表明生命周期与Activity一致。换句话说,我们可以自定义作用域的粒度(比如@PerFragment, @PerUser等等)。
@Component 组件,创建一个 Dagger 容器,作为获取依赖项的入口
也可以称为注入器。是@Inject和@Module之间的桥梁,主要职责是把二者组合在一起。@Component注解用来标记接口或者抽象类。所有的components都可以通过它的modules知道它所提供的依赖范围。一个Component可以依赖一个或多个Component,并拿到被依赖Component暴露出来的实例,Component的dependencies属性就是确定依赖关系的实现。
@Subcomponent 子组件,用来定义更加细致的作用域
@Qualifier 限定符,当有两个相同的依赖时,它们都继承同一个父类或者均实现同一个接口。当它们被提供给高层时,Component 就不知道我们到底要提供哪一个依赖对象了,因为它找到了两个。@Qualifier不是直接标记在属性上的,而是用来自定义注解的
@Named @Named是@Qualifier 的一种实现。@Named传递的值只能是字符串
一个简单的例子


    public class Watch {

        @Inject
        public Watch(){
    
        }
    
        public void work(){
            ILog.LogDebug("手表工作了");
        }
    
    }

    @Component
    public interface MainActivityComponent {
    
        void inject(MainActivity mainActivity);
    
    }

    public class MainActivity extends AppCompatActivity {

        @Inject
        Watch mWatch;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            DaggerMainActivityComponent.builder().build().inject(this);
            mWatch.work();
        }
    
    }

使用module的例子


    public class Watch {

        //注意这里去掉了@Inject ,改为使用下面provide提供的对象
        public Watch(){
    
        }
    
        public void work(){
            ILog.LogDebug("手表工作了");
        }
    
    }

    @Module
    public class WatchModule {

        @Provides
        public Watch provideWatch(){
            return new Watch();
        }

    }


    //这里新建了module,用来提供watch实例
    @Component(modules = {WatchModule.class)
    public interface MainActivityComponent {
    
        void inject(MainActivity mainActivity);
    
    }
    

    public class MainActivity extends AppCompatActivity {

        @Inject
        Watch mWatch;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            DaggerMainActivityComponent.builder().build().inject(this);
            mWatch.work();
        }
    
    }

@Named标识符使用


    public class Man extends People{

        public Man(){
    
        }

        @Override
        public void work() {
            ILog.LogDebug("man work");
        }
    }

    public class Woman extends People{

        public Woman(){
    
        }
    
    
        @Override
        public void work() {
            ILog.LogDebug("woman work");
        }
    }


    @Module
    public class PeopleModule {

        @Named("man")
        @Provides
        public People provideMan(){
            return new Man();
        }

        @Named("woman")
        @Provides
        public People provideWoman(){
            return new Woman();
        }
    }

    @Component(modules = {WatchModule.class, PeopleModule.class})
    public interface MainActivityComponent {

        void inject(MainActivity mainActivity);
    }

    public class MainActivity extends AppCompatActivity {

        @Inject
        Watch mWatch;

        @Inject
        @Named("man")
        public People peopleMan;
    
        @Inject
        @Named("woman")
        public People peopleWoman;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            DaggerMainActivityComponent.builder().build().inject(this);
            mWatch.work();
            peopleWoman.work();
            peopleMan.work();
        }
    
    }
@Qualifier标识符使用


    public class Man extends People{

        public Man(){
    
        }

        @Override
        public void work() {
            ILog.LogDebug("man work");
        }
    }

    public class Woman extends People{

        public Woman(){
    
        }
    
    
        @Override
        public void work() {
            ILog.LogDebug("woman work");
        }
    }

    @Qualifier
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ManPeople {
    }

    @Qualifier
    @Retention(RetentionPolicy.RUNTIME)
    public @interface WomanPeople {

    }


    @Module
    public class PeopleModule {

        @ManPeople
        @Provides
        public People provideMan(){
            return new Man();
        }

        @WomanPeople
        @Provides
        public People provideWoman(){
            return new Woman();
        }
    }

    @Component(modules = {WatchModule.class, PeopleModule.class})
    public interface MainActivityComponent {

        void inject(MainActivity mainActivity);
    }

    public class MainActivity extends AppCompatActivity {

        @Inject
        Watch mWatch;

        @Inject
        @ManPeople
        public People peopleMan;
    
        @Inject
        @WomanPeople
        public People peopleWoman;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            DaggerMainActivityComponent.builder().build().inject(this);
            mWatch.work();
            peopleWoman.work();
            peopleMan.work();
        }
    
    }
@Singleton标识符使用


    @Module
    public class GsonModule {
    
        @Singleton   //使用Singleton修饰,保证在本Activity中多个Gson对象为同一个单例
        @Provides
        public Gson provideGson(){
            return new Gson();  //不使用Singleton修饰,每次都会new一个新的对象
        }
        
    }

    @Singleton  //同样需要标注
    @Component(modules = {WatchModule.class, PeopleModule.class, GsonModule.class})
    public interface MainActivityComponent {

        void inject(MainActivity mainActivity);

        void inject(SecondActivity secondActivity);

    }
    
    public class MainActivity extends AppCompatActivity {

        @Inject
        Gson mGson;
    
        @Inject
        Gson mGson2;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            DaggerMainActivityComponent.builder().build().inject(this);
            ILog.LogDebug("gons1 hasCode : "+mGson.hashCode()+", gson2 hasCode: "+mGson2.hashCode());

        }
    
    }

    打印结果:
    gons1 hasCode : 76774892, gson2 hasCode: 76774892

    Gson 在 MainActivity 中是单例,如果再创建一个 SecondActivity,SecondActivity 创建的Gson 的内存地址和 MainActivity 创建的 Gson 的内存地址是不同的。因为 Gson 只是保证在MainActivityComponent中是单例的,我们创建SecondActivity,就会重新创建一个Component,这样只能保证Gson是局部单例(MainActivity中)
    查看@Singleton的源码其实就是用@Scope 标识的注解。为了使 Gson 变为全局单例,我们可以用@Scope 结合Application来实现。当然也可以用@Singleton结合Application来实现,只是用@Scope可以自定义注解名称,这更灵活一些。
@Scope标识符使用


    @Scope
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ApplicationScope {
    
    }

    @Module
    public class GsonModule {

        @ApplicationScope
        @Provides
        public Gson provideGson(){
            return new Gson();
        }
    }

    @ApplicationScope
    @Component(modules = {GsonModule.class})
    public interface MainActivityComponent {

        void inject(MainActivity mainActivity);
        void inject(SecondActivity secondActivity);
    }

    public class App extends Application {

        MainActivityComponent mainActivityComponent;
        
        @Override
        public void onCreate() {
            super.onCreate();
            mainActivityComponent = DaggerMainActivityComponent.builder().build();
        }
    
        public static App get(Context context){
            return (App) context.getApplicationContext();
        }
    
        public MainActivityComponent getMainActivityComponent(){
            return mainActivityComponent;
        }
    
    }


    public class MainActivity extends AppCompatActivity {

        @Inject
        Gson mGson;
    
        @Inject
        Gson mGson2;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            App.get(MainActivity.this).getMainActivityComponent().inject(this);

            ILog.LogDebug("gons1 hasCode : "+mGson.hashCode()+", gson2 hasCode: "+mGson2.hashCode());

        }
    
    }

    public class SecondActivity extends AppCompatActivity {

        @Inject
        Gson mGson2;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            App.get(SecondActivity.this).getMainActivityComponent().inject(this);
            ILog.LogDebug("gson2 hascode: "+mGson2.hashCode());
        }
    }

    MainActivity会打印:
    gons1 hasCode : 183205259, gson2 hasCode: 183205259

    SecondActivity会打印:
    gson2 hascode: 183205259

    上面两个activity打印的gson实例 hascode都是一样的,使用的都是全局的component。component中的gson实例肯定也是全局的。

@Component的dependencies
    @Component也可以用dependencies依赖于其他Component。


    public class SuperMan extends People{

        public SuperMan(){
    
        }
    
        @Override
        public void work() {
            ILog.LogDebug("super man work");
        }
    }

    @Module
    public class SuperManModule {

        @Provides
        public SuperMan provideSuperMan(){
            return new SuperMan();
        }

    }


    @Component(modules = SuperManModule.class)
    public interface SuperManComponent {
    
        SuperMan getSuperman();
    }
    
    @ApplicationScope
    @Component(modules = {WatchModule.class, PeopleModule.class},dependencies = SuperManComponent.class)
    public interface MainActivityComponent {

        void inject(MainActivity mainActivity);

        void inject(SecondActivity secondActivity);

    }

    public class App extends Application {

        MainActivityComponent mainActivityComponent;
        
        @Override
        public void onCreate() {
            super.onCreate();

            //注意这里需要传DaggerSuperManComponent实例
            mainActivityComponent = DaggerMainActivityComponent.builder().superManComponent(DaggerSuperManComponent.builder().build()).build();
        }
    
        public static App get(Context context){
            return (App) context.getApplicationContext();
        }
    
        public MainActivityComponent getMainActivityComponent(){
            return mainActivityComponent;
        }
    
    }

    public class MainActivity extends AppCompatActivity {

        @Inject
        SuperMan superMan;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            App.get(MainActivity.this).getMainActivityComponent().inject(this);
            superMan.work();

        }
    
    }

Dagger2懒加载模式
    Dagger2提供了懒加载模式,在@Inject的时候不初始化,而是使用的时候,调用get方法来获取实例。


    public class MainActivity extends AppCompatActivity {

        @Inject
        Lazy<SuperMan> superManLazy;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            App.get(MainActivity.this).getMainActivityComponent().inject(this);
            SuperMan superMan = superManLazy.get();
            superMan.work();

        }
    
    }

Component的几种创建方式

✔ 接口方式(@Component)
✔ 手动构建方式(使用 DaggerAppComponent.builder() / factory())
⭐ 一、方式 1:传统接口 + 自动生成 Component(最常见)
🔧 写一个 @Component 接口,Dagger 会为它生成实现类。

@Singleton
@Component(modules = { AppModule.class, NetworkModule.class })
public interface AppComponent {
    void inject(MainActivity activity);
}
编译后 Dagger 自动生成:DaggerAppComponent,你只需要这样创建:

AppComponent appComponent = DaggerAppComponent.create();
📌 create() 有什么特点?
⭐ 二、方式2 使用 Builder自定义创建
这是 官方推荐的方式,适用于需要给 Module 传参时。
使用 Builder 来创建 Component
Step 1:写 Component

@Singleton
@Component(modules = {AppModule.class})
public interface AppComponent {

    @Component.Builder
    interface Builder {

        //作用:把 runtime 对象绑定进依赖图
        //Application 不是 Dagger 创建的,它是 Android 创建的,
        //所以 Dagger 无法自己 new 一个。
        //你必须告诉 Dagger 使用哪个 Application。
        //不是必须有的方法,只有当你的依赖图中需要 Application 时才需要。
        @BindsInstance
        Builder application(Application app);

        //作用:让外部传入一个 Module 实例
        //为什么?因为你的 Module 有构造参数:
        //public class AppModule {
        //    Application app;
        //    public AppModule(Application app) {
        //        this.app = app;
        //    }
        //}
        //如果你的 Module 是这样:那就不需要
        //@Module
        //class NetworkModule {}

        Builder appModule(AppModule module);

        //✔ 唯一必需的方法
        //这是 Builder 构建 Component 的出口,没有它你无法得到 AppComponent。
        //Dagger 要求 Builder 必须有 build() 方法:
        //返回类型必须是 Component 类型
        //名字可以不是 build(),但必须有 一个方法返回 Component
        AppComponent build();
    }

    void inject(MyApplication app);
}

Step 2:使用 Builder 创建

AppComponent appComponent = DaggerAppComponent.builder()
        .application(this)
        .appModule(new AppModule(this))
        .build();
📝 Builder 特点:
⭐ 三、方式3 使用 Factory自定义创建
🔧 使用 Factory 来创建 Component(比 Builder 更推荐)
Step 1:写 Component

@Singleton
@Component(modules = {AppModule.class})
public interface AppComponent {

    @Component.Factory
    interface Factory {

        AppComponent create(
            @BindsInstance Application app,
            AppModule appModule
        );
    }

    void inject(MyApplication app);
}
Step 2:使用 Factory 创建

AppComponent appComponent =
    DaggerAppComponent.factory().create(this, new AppModule(this));
📝 Factory 特点:

java+rxjava3+dagger2+okhttp+retrofit+room+viewmodel的一个例子

build.gradle依赖

dependencies {

    implementation 'com.google.code.gson:gson:2.10.1'

    // Retrofit + OkHttp
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    implementation 'com.squareup.okhttp3:okhttp:4.11.0'
    implementation 'com.squareup.okhttp3:logging-interceptor:4.11.0'
    implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'

    // RxJava3 + RxAndroid
    implementation 'io.reactivex.rxjava3:rxjava:3.1.6'
    implementation 'io.reactivex.rxjava3:rxandroid:3.0.2'

    // Room with RxJava3 support
    implementation 'androidx.room:room-runtime:2.6.1'
    implementation 'androidx.room:room-rxjava3:2.6.1'
    annotationProcessor 'androidx.room:room-compiler:2.6.1'

    // Dagger2
    implementation 'com.google.dagger:dagger:2.59.2'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.59.2'

    implementation "com.google.dagger:dagger-android:2.59.2"
    //implementation "com.google.dagger:dagger-android-support:2.59.2"
    annotationProcessor "com.google.dagger:dagger-android-processor:2.59.2"

}
AppModule

@Module
public class AppModule {

    @Provides
    @Singleton
    Context provideContext(Application application){
        return application.getApplicationContext();
    }

}
PostBean

@Entity(tableName = TABLE_NAME)
public class PostBean {

    public static final String TABLE_NAME = "post_table";

    @PrimaryKey
    @SerializedName("id")
    public int id;

    @SerializedName("userID")
    public int userId;

    @SerializedName("title")
    public String title;


    @SerializedName("body")
    public String body;
}
ApiService

public interface ApiService {

    @GET("posts")
    Single<List<PostBean>> getPostBean();
}
NetWorkModule

@Module
public class NetWorkModule {

    private static final String BASE_URL = "https://jsonplaceholder.typicode.com/";

    @Provides
    @Singleton
    HttpLoggingInterceptor provideLogging(){
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        return loggingInterceptor;
    }


    @Provides
    @Singleton
    OkHttpClient provideOkHttpClient(HttpLoggingInterceptor loggingInterceptor){
        return new OkHttpClient.Builder()
                .addInterceptor(loggingInterceptor)
                .callTimeout(30, TimeUnit.SECONDS)
                .build();
    }

    @Provides
    @Singleton
    Gson provideGson(){
        return new GsonBuilder().create();
    }

    @Provides
    @Singleton
    Retrofit provideRetrofit(OkHttpClient client , Gson gson){
        return new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(client)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJava3CallAdapterFactory.createWithScheduler(Schedulers.io()))
                .build();
    }



    @Provides
    @Singleton
    ApiService provideApiService(Retrofit retrofit){
        return retrofit.create(ApiService.class);
    }

}
PostBeanDao

@Dao
public interface PostBeanDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    Completable insertPosts(List<PostBean> posts);

    @Query("SELECT * FROM "+PostBean.TABLE_NAME)
    Flowable<List<PostBean>> observeAllPosts();

    @Query("SELECT * FROM "+PostBean.TABLE_NAME)
    Single<List<PostBean>> getAllPostsOnce();
}
PostBeanRepository

@Singleton
public class PostBeanRepository {

    private ApiService apiService;
    private PostBeanDao postBeanDao;

    @Inject
    public PostBeanRepository(ApiService apiService, PostBeanDao postDao){
        this.apiService = apiService;
        this.postBeanDao = postDao;
    }

    public Single<List<PostBean>> fetchAndStorePosts(){
            return apiService.getPostBean().flatMap(
                    postBeans ->
                            postBeanDao.insertPosts(postBeans).andThen(
                                    postBeanDao.getAllPostsOnce()
                            )
            );
    }

    public Flowable<List<PostBean>> observeAllPosts(){
        return postBeanDao.observeAllPosts();
    }

}
AppDatabase

@Database(entities = {PostBean.class},version = 1,exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
    abstract PostBeanDao postBeanDao();
}
DatabaseModule

@Module
public class DatabaseModule {

    @Provides
    @Singleton
    AppDatabase provideAppDatabase(Context context){
        return Room.databaseBuilder(context,AppDatabase.class,"sample.db")
                .build();
    }

    @Provides
    @Singleton
    PostBeanDao providePostDao(AppDatabase db){
        return db.postBeanDao();
    }
}
MainViewModel

public class MainViewModel  extends ViewModel {

    private PostBeanRepository postBeanRepository;

    @Inject
    public MainViewModel(PostBeanRepository postBeanRepository){
        this.postBeanRepository = postBeanRepository;
    }

    public Flowable<List<PostBean>> observeAllPosts(){
        return postBeanRepository.observeAllPosts();
    }
}
ViewModelKey

@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@MapKey
public @interface ViewModelKey {
    Class<? extends ViewModel> value();
}
ViewModelModule

@Module
public abstract class ViewModelModule {


    //Binds注解的作用
    //告诉 Dagger:
    //当需要 ViewModel 类型(或 Map 中的这个 Key)时,用 UserViewModel 来提供实现。
    //因为 UserViewModel 是 ViewModel 的子类,所以可以安全转换。
    //不需要写 return new UserViewModel(),Dagger 会自动生成代码调用构造函数(前提是构造函数有 @Inject)。

    //在多 ViewModel 注入场景中,通常希望用一个 Map 来存放不同 ViewModel 的绑定:
    //@IntoMap → 把绑定放进一个 Map,而不是单独提供。
    //@ViewModelKey(UserViewModel.class) → 指定 Map 的 key。
    //Map 类型最终是:Map<Class<? extends ViewModel>, Provider<ViewModel>>
    //Dagger 会生成这个 Map,把不同的 ViewModel 绑定到对应 key。

    @Binds
    @IntoMap
    @ViewModelKey(MainViewModel.class)
    abstract ViewModel bindMainViewModel(MainViewModel mainViewModel);

    //绑定一个通用的 ViewModelFactory(DaggerViewModelFactory)到 ViewModelProvider.Factory。
    //这个工厂内部会使用上面 Map 来创建指定 ViewModel。
    //好处:在 Activity/Fragment 中直接调用:ViewModel vm = new ViewModelProvider(this, factory).get(UserViewModel.class);

    @Binds
    abstract ViewModelProvider.Factory bindViewModelFactory(DaggerViewModelFactory daggerViewModelFactory);

}
ActivityBindingModule

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

@Module
public abstract class ActivityBindingModule {


    //把这个 Activity 的 injector factory 注册进去,供 DispatchingAndroidInjector 分发使用。
    @ContributesAndroidInjector
    abstract MainActivity bindMainActivity();

    @ContributesAndroidInjector
    abstract SecondActivity bindSecondActivity();
}


AppComponent


AndroidInjectionModule.class
//AndroidInjectionModule 是 Dagger Android 提供的内置 Module,它主要负责:
//提供 Activity、Fragment、Service 等 Android 组件的默认 Injector
//生成 DispatchingAndroidInjector,让你的 Application 能够提供 injector 给这些组件
//它本身一般不需要修改,Dagger 已经写好了。
//核心作用:
//提供 DispatchingAndroidInjector<Object>
//允许你在 Application 中写:
@Inject
DispatchingAndroidInjector<Object> androidInjector;
//这样 Application 就实现了 HasAndroidInjector 接口:
@Override
public AndroidInjector<Object> androidInjector() {
    return androidInjector;
}
//Activity / Fragment / Service 执行 AndroidInjection.inject(this) 时,就可以拿到 injector


@Singleton
@Component(modules = {AndroidInjectionModule.class,AppModule.class,NetWorkModule.class, DatabaseModule.class, ViewModelModule.class})
public interface AppComponent {
    void inject(MyApp app);

    @Component.Factory
    interface Factory{
        AppComponent create(@BindsInstance Application application);
    }
}
DaggerViewModelFactory

public class DaggerViewModelFactory implements ViewModelProvider.Factory {

    private final Map<Class<? extends ViewModel>, Provider<ViewModel>> creators;

    @Inject
    public DaggerViewModelFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> creators) {
        this.creators = creators;
    }

    @NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
        Provider<? extends ViewModel> creator = creators.get(modelClass);
        if (creator == null) {
            for (Map.Entry<Class<? extends ViewModel>, Provider<ViewModel>> entry : creators.entrySet()) {
                if (modelClass.isAssignableFrom(entry.getKey())) {
                    creator = entry.getValue();
                    break;
                }
            }
        }

        if (creator == null) {
            throw new IllegalArgumentException("Unknown ViewModel class: " + modelClass);
        }

        try {
            return (T) creator.get();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
MyApp


//HasActivityInjector 是 Dagger Android 提供的接口:
public interface HasActivityInjector {
    AndroidInjector<Activity> activityInjector();
}
//它的作用:
//让 Application 对外提供一个 Activity 注入器。也就是说,当你在 Activity 中调用:
AndroidInjection.inject(this)
//AndroidInjection 会自动向 Application 查询:
if (application instanceof HasActivityInjector) {
    AndroidInjector<Activity> injector = application.activityInjector();
    injector.inject(activity);
}

public class MyApp extends Application implements HasAndroidInjector {

    private static AppComponent appComponent;

    //这是 Dagger 自动生成的 多 Activity 注入器总路由器。
    @Inject
    DispatchingAndroidInjector<Object> androidInjector;

    @Override
    public void onCreate() {
        super.onCreate();

        //生成appComponent实例
        appComponent = DaggerAppComponent.factory().create(this);

        //这行代码执行后:
        //dispatchingAndroidInjector 会被 Dagger 自动注入
        //Application 现在具备 “Activity 注入器”
        appComponent.inject(this);


    }

    public static AppComponent getAppComponent(){
        return appComponent;
    }

    @Override
    public AndroidInjector<Object> androidInjector() {
        return androidInjector;
    }
}
TestViewModelFactoryActivity

public class TestViewModelFactoryActivity extends AppCompatActivity {

    //这个注入器的实例是AndroidInjectionModule.class提供的
    @Inject
    ViewModelProvider.Factory viewModelProviderFactory;

    private MainViewModel mainViewModel;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {

        //让 Dagger 在 Activity onCreate() 之前,把需要的依赖注入到当前 Activity 中。
        //为什么要放在 super.onCreate() 之前?
        //一些依赖可能在 super.onCreate() 中用到
        //Activity 的生命周期回调链会提前访问成员变量
        //注入必须尽早,否则为空指针异常
        //如果是 Fragment,则使用:AndroidSupportInjection.inject(this);
        //和手工activityComponent.inject(activity)本质做的是同一件事,为 Activity 创建对应的子组件,然后调用 inject(activity) 把依赖注入进去。

        AndroidInjection.inject(this);

        super.onCreate(savedInstanceState);
        mainViewModel = new ViewModelProvider(this,viewModelProviderFactory).get(MainViewModel.class);

        setContentView(R.layout.activity_main);

    }

    public void goSecondAcitivty(View view){
        Intent intent = new Intent(TestViewModelFactoryActivity.this, SecondActivity.class);
        startActivity(intent);
    }
}
解释上面遇到的注入器DispatchingAndroidInjector
✅AndroidInjection.inject(this) 和 “手工 activityComponent.inject(activity)” 的本质功能
它们本质做的是同一件事:为 Activity 创建对应的子组件,然后调用 inject(activity) 把依赖注入进去。
区别在于:
AndroidInjection.inject(this):自动注入,子组件自动创建,依赖 dagger-android
手写 activityComponent.inject(activity):手工注入,子组件手动创建,完全手动管理

✅ 方式 1:AndroidInjection.inject(this)(自动注入)
这个方式依赖:
HasActivityInjector
DispatchingAndroidInjector<Activity>
@ContributesAndroidInjector
AndroidInjection.inject(this)

你只要:
✔ Application 中注入 androidInjector

DaggerAppComponent.create().inject(this);
✔ 每个 Activity 里写:

AndroidInjection.inject(this);
super.onCreate(savedInstanceState);
✔ Dagger 自动为每个 Activity 生成子 Component:

@ContributesAndroidInjector
abstract MyActivity contributeMyActivity();
✅优点
无需自己写 Component、Builder、inject 方法,Dagger 全自动处理
模块化好:每个 Activity 的 module 自动关联
代码极简
避免因忘记 inject 造成的 null
更适合大型项目(几十上百个 Activity)

缺点
依赖 dagger-android(已停止维护,但仍稳定)

✅ 方式 2:手写 ActivityComponent 并手动注入
你可能要写很多代码:

✔ 定义 ActivityComponent

@ActivityScope
@Component(dependencies = AppComponent.class, modules = XActivityModule.class)
interface XActivityComponent {
    void inject(XActivity activity);
}
✔ 手动创建 Component

component = DaggerXActivityComponent.builder()
        .appComponent(((MyApp)getApplication()).getAppComponent())
        .build();
component.inject(this);
✅优点
不依赖 dagger-android,完全纯 Dagger,掌控更强
对非常复杂的组件结构可能更灵活

缺点
样板代码巨大
你要给每个 Activity 写自己的 component
容易忘记调用 inject() → 注入失败
模块化差