Dagger2的依赖关系的分析和理解

前端之家收集整理的这篇文章主要介绍了Dagger2的依赖关系的分析和理解前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

Student.java文件

public class Student {
    private int age;
    private String name;
    public Student(int age,String name) {
        this.age = age;
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }
}

在appcomponent包下面,三个文件:AppComponent.java、AppModule.java、PerActivity.java。

AppComponent.java文件

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
    Context getApplicationContext();
    Student getStudent();
}


AppModule.java文件
@Module
public class AppModule {
    private static int count = 0;
    private App app;
    public AppModule(App app) {
        this.app = app;
    }

    @Provides
    @Singleton
    Student providerStudent() {
        return new Student(23,"jack" + String.valueOf(count++));
    }

    @Provides
    @Singleton
    Context providerApplicationContext() {
        return app.getApplicationContext();
    }
}


PerActivity.java文件
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface PerActivity {
}


在包MainComponent包下的两个文件

ConstructorComponent.java文件

@PerActivity
@Component(modules = ConstructorModule.class)
public interface ConstructorComponent {
    void inject(MainActivity mainActivity);
}

ConstructorModule.java文件
@PerActivity
@Module
public class ConstructorModule {

    public ConstructorModule() {
    }
}



public class App extends Application {
    private AppComponent appComponent;

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

        appComponent = DaggerAppComponent.builder().appModule(new AppModule(this)).build();
    }

    public AppComponent getAppComponent() {
        return appComponent;
    }
}


public class MainActivity extends AppCompatActivity {
    Button btn;

    @Inject
    Student student;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn = (Button) findViewById(R.id.btn);

        DaggerConstructorComponent.builder().appComponent(((App)getApplication()).getAppComponent())
                .constructorModule(new ConstructorModule()).build().inject(this);

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                test();
            }
        });
    }

    private void test() {
        Toast.makeText(getApplicationContext(),student.getName() + "," + student.getAge(),Toast.LENGTH_SHORT).show();
    }
}


编译发生如下错误
Error:(14,10) 错误: com.robot.ddagger.bean.Student cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
com.robot.ddagger.MainActivity.student
[injected field of type: com.robot.ddagger.bean.Student student]

分析这里为什么会出现问题呢?

先看看在dagger2帮我们生成了哪些文件

AppModule_ProviderApplicationContextFactory.java

AppModule_ProviderStudentFactory.java

DaggerAppComponent.java

MainActivity_MembersInjector.java // 生成这个文件是因为在MainActivity中有@Inject Student student;,如果去掉这句话则不会生成这个文件


按照dagger2的规则应该也会对应生成,DaggerConstructorComponent.java文件,但是这里并没有生成

看看错误提示,翻译一下:不能没有一个@Inject构造函数或从@ Provides-提供或@产生注解方法


不好理解,还是从生成的MainActivity_MembersInjector.java分析。

@Generated("dagger.internal.codegen.ComponentProcessor")
public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
  private final MembersInjector<AppCompatActivity> supertypeInjector;
  private final Provider<Student> studentProvider;

  public MainActivity_MembersInjector(MembersInjector<AppCompatActivity> supertypeInjector,Provider<Student> studentProvider) {  
    assert supertypeInjector != null;
    this.supertypeInjector = supertypeInjector;
    assert studentProvider != null;
    this.studentProvider = studentProvider;
  }

  @Override
  public void injectMembers(MainActivity instance) {  
    if (instance == null) {
      throw new NullPointerException("Cannot inject members into a null reference");
    }
    supertypeInjector.injectMembers(instance);
    instance.student = studentProvider.get();
  }

  public static MembersInjector<MainActivity> create(MembersInjector<AppCompatActivity> supertypeInjector,Provider<Student> studentProvider) {  
      return new MainActivity_MembersInjector(supertypeInjector,studentProvider);
  }
}
可以看到这里有个Provider<Student> studentProvider;,也就是说MainActivity_MembersInjector.java需要这个studentProvider。

这里如果在MainActivity.java中有其他的@Inject XXX xxx,那么也会在MainActivity_MembersInjector.java中产生,Provider<XXX> xxxProvider。


我们也知道DaggerXXXComponent调用inject()函数的时候,将会调用相关的XXX_MembersInjector中的函数

对应于这里的情况就是DaggerConstructorComponent中的inject()函数,会调用这里的MainActivity_MembersInjector中函数

首先调用的当然是这里的MainActivity_MembersInjector中的create()了。


那么问题来了,这里的Provider<Student> studentProvider如何从

DaggerConstructorComponent传递给MainActivity_MembersInjector的create()呢?也就是说DaggerConstructorComponent必然自己也有

Provider<Student> studentProvider这个。回到我们的ConstructorComponent.java的定义。

@PerActivity
@Component(modules = ConstructorModule.class)
public interface ConstructorComponent {
    void inject(MainActivity mainActivity);
}


可以看到这里ConstructorComponent中至于ConstructorModule有关,再看看ConstructorModule的定义,发现它并没有提供什么。
@PerActivity
@Module
public class ConstructorModule {

    public ConstructorModule() {
    }
}


看到这里应该有点明白了吧。简单的理清一下思路。

(1)在MainActivity中的@Inject Student student,导致生成了MainActivity_MembersInjector,而且是构造函数带有参数Provider<Student>的。

(2)而我们定义的ConstructorComponent中可以知道,MainActivity是目标类,而ConstructorModule是目标依赖类。

生成的DaggerConstructorComponent的inject到时候会调用MainActivity_MembersInjector类,需要将Provider<Student>传递给

MainActivity_MembersInjector类,但是发现ConstructorModule并没有提供任何有关Provider<Student>的东西。


所以导致DaggerConstructorComponent生成不了。

解决方法也很简单,你需要告诉DaggerConstructorComponent,你提供了Provider<Student>了。

@PerActivity
@Component(dependencies = AppComponent.class,modules = ConstructorModule.class)
public interface ConstructorComponent {
    void inject(MainActivity mainActivity);
}


看看AppComponent的定义,已经提供了Student了。
@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
    Context getApplicationContext();
    Student getStudent();
}

这样子DaggerConstructorComponent就可以把Provider<Student>传递给MainActivity_MembersInjector了。

看看生成的DaggerConstructorComponent.java文件

@Generated("dagger.internal.codegen.ComponentProcessor")
public final class DaggerConstructorComponent implements ConstructorComponent {
  private Provider<Student> getStudentProvider;
  private MembersInjector<MainActivity> mainActivityMembersInjector;

  private DaggerConstructorComponent(Builder builder) {  
    assert builder != null;
    initialize(builder);
  }

  public static Builder builder() {  
    return new Builder();
  }

  private void initialize(final Builder builder) {  
    this.getStudentProvider = new Factory<Student>() {
      private final AppComponent appComponent = builder.appComponent;
      @Override public Student get() {
        Student provided = appComponent.getStudent();
        if (provided == null) {
          throw new NullPointerException("Cannot return null from a non-@Nullable component method");
        }
        return provided;
      }
    };
    this.mainActivityMembersInjector = MainActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(),getStudentProvider);
  }

  @Override
  public void inject(MainActivity mainActivity) {  
    mainActivityMembersInjector.injectMembers(mainActivity);
  }

  public static final class Builder {
    private ConstructorModule constructorModule;
    private AppComponent appComponent;
  
    private Builder() {  
    }
  
    public ConstructorComponent build() {  
      if (constructorModule == null) {
        this.constructorModule = new ConstructorModule();
      }
      if (appComponent == null) {
        throw new IllegalStateException("appComponent must be set");
      }
      return new DaggerConstructorComponent(this);
    }
  
    public Builder constructorModule(ConstructorModule constructorModule) {  
      if (constructorModule == null) {
        throw new NullPointerException("constructorModule");
      }
      this.constructorModule = constructorModule;
      return this;
    }
  
    public Builder appComponent(AppComponent appComponent) {  
      if (appComponent == null) {
        throw new NullPointerException("appComponent");
      }
      this.appComponent = appComponent;
      return this;
    }
  }
}


重点代码,可以看到这里的studentProvider是AppComponent提供的。并且把studentProvider传递给MainActivity_MembersInjector了。
private void initialize(final Builder builder) {
        this.getStudentProvider = new Factory<Student>() {
            private final AppComponent appComponent = builder.appComponent;

            @Override
            public Student get() {
                Student provided = appComponent.getStudent();
                if (provided == null) {
                    throw new NullPointerException("Cannot return null from a non-@Nullable component method");
                }
                return provided;
            }
        };
        this.mainActivityMembersInjector = MainActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(),getStudentProvider);
    }


本文资源代码下载 :https://github.com/robotlife/DDaggerDepend

原文链接:https://www.f2er.com/javaschema/283856.html

猜你在找的设计模式相关文章