Dagger2 生成代碼學(xué)習(xí)筆記

上一篇記錄了如何使用Dagger秆吵,其中還漏了一些內(nèi)容淮椰,回頭再補(bǔ)。今天來(lái)看看Dagger在預(yù)編譯時(shí)期生成的輔助代碼纳寂,看看Dagger做依賴注入的實(shí)現(xiàn)原理是咋樣的主穗。
還是從上一篇中最簡(jiǎn)單的Sample開始。先看下代碼:
MainActivity:

public class MainActivity extends AppCompatActivity {

    @Inject
    UserModel user;

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

        DaggerUserComponent.builder()
                .userModule(new UserModule())
                .build()
                .inject(this);

        ((TextView) findViewById(R.id.text_view)).setText("Name:" + user.getName() + "::Age:" + user.getAge());
    }
}

UserModel:

public class UserModel {

    private String name;
    private int age;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

UserModule:

@Module
public class UserModule {

    UserModule() {}

    @Provides
    UserModel provideUsers() {
        UserModel user = new UserModel();
        user.setName("lala");
        user.setAge(18);
        return user;
    }
}

UserComponent:

@Component(modules = {UserModule.class})
public interface UserComponent {
    void inject(MainActivity mainActivity);
}

運(yùn)行結(jié)果如下:


Screenshot_2017-02-08-11-40-46.png

OK毙芜,咱們先來(lái)看看Dagger為我們上面的代碼生成了哪些東東忽媒。
咱們自己的類:
1.MainActivity
2.UserComponent
3.UserModel
4.UserModule
Dagger生成的類:
1.DaggerUserComponent
2.UserModule_ProvideUsersFactory
3.MainActivity_MembersInjector
好,下面來(lái)逐個(gè)看看這幾個(gè)生成類

直接從我們執(zhí)行注入的代碼下手:

DaggerUserComponent.builder()
                .userModule(new UserModule())
                .build()
                .inject(this);

可以看到腋粥,我們通過Builder方式晦雨,傳一個(gè)UserModule的實(shí)例,build一個(gè)DaggerUserComponent的實(shí)例出來(lái)隘冲,然后調(diào)用 inject 方法執(zhí)行注入操作闹瞧。
下面嘍一眼DaggerUserComponent的代碼。
DaggerUserComponent:

@Generated("dagger.internal.codegen.ComponentProcessor")
public final class DaggerUserComponent implements UserComponent {
  private Provider<UserModel> provideUsersProvider;
  private MembersInjector<MainActivity> mainActivityMembersInjector;

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

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

  public static UserComponent create() {  
    return builder().build();
  }

  private void initialize(final Builder builder) {  
    this.provideUsersProvider = UserModule_ProvideUsersFactory.create(builder.userModule);
    this.mainActivityMembersInjector = MainActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), provideUsersProvider);
  }

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

  public static final class Builder {
    private UserModule userModule;
  
    private Builder() {  
    }
  
    public UserComponent build() {  
      if (userModule == null) {
        this.userModule = new UserModule();
      }
      return new DaggerUserComponent(this);
    }
  
    public Builder userModule(UserModule userModule) {  
      if (userModule == null) {
        throw new NullPointerException("userModule");
      }
      this.userModule = userModule;
      return this;
    }
  }
}

這個(gè)類非常簡(jiǎn)單展辞,它實(shí)現(xiàn)了咱們寫的UserComponent接口奥邮,實(shí)現(xiàn)了inject方法。重點(diǎn)在初始化 (initialize) 和注入 (inject) 兩個(gè)方法纵竖。

private Provider<UserModel> provideUsersProvider;
private MembersInjector<MainActivity> mainActivityMembersInjector;

private void initialize(final Builder builder) {  
    this.provideUsersProvider = UserModule_ProvideUsersFactory.create(builder.userModule);
    this.mainActivityMembersInjector = MainActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), provideUsersProvider);
  }

可以看到漠烧,initialize這個(gè)方法創(chuàng)建了兩個(gè)成員變量杏愤,provideUsersProvidermainActivityMembersInjector
創(chuàng)建Provider的代碼引出了第二個(gè)生成類: UserModule_ProvideUserFactory

@Generated("dagger.internal.codegen.ComponentProcessor")
public final class UserModule_ProvideUsersFactory implements Factory<UserModel> {
  private final UserModule module;

  public UserModule_ProvideUsersFactory(UserModule module) {  
    assert module != null;
    this.module = module;
  }

  @Override
  public UserModel get() {  
    UserModel provided = module.provideUsers();
    if (provided == null) {
      throw new NullPointerException("Cannot return null from a non-@Nullable @Provides method");
    }
    return provided;
  }

  public static Factory<UserModel> create(UserModule module) {  
    return new UserModule_ProvideUsersFactory(module);
  }
}

顧名思義已脓,UserModule_ProvideUsersFactory 是一個(gè)工廠類珊楼,此類用來(lái)生產(chǎn)我們用 @Inject 注解的UserModel實(shí)例。
上面這句是屁話度液,UserModel的真正的實(shí)例并不在這里生產(chǎn)厕宗,可以看到,這個(gè)“偽工廠”接受一個(gè)咱們寫的UserModule的實(shí)例堕担,然后在get方法中調(diào)用UserModule的provideUsers()方法(咱們自己寫的)已慢,把拿到的UserModel實(shí)例返回。
咱們回到DaggerUserComponent霹购,再瞄一眼初始化的第一句代碼:
this.provideUsersProvider = UserModule_ProvideUsersFactory.create(builder.userModule);
在這里創(chuàng)建了一個(gè)生產(chǎn)UserModel實(shí)例的工廠實(shí)例佑惠。該實(shí)例的get方法返回一個(gè)UserModel的實(shí)例(從Module的provide方法中拿到的)。
OK齐疙,拿到了Provider的實(shí)例膜楷,來(lái)看看初始化的第二行代碼:
this.mainActivityMembersInjector = MainActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), provideUsersProvider);
這里引出了第三個(gè)生成類宫患,MainActivity_MembersInjector.

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

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

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

  public static MembersInjector<MainActivity> create(MembersInjector<AppCompatActivity> supertypeInjector, Provider<UserModel> userProvider) {  
      return new MainActivity_MembersInjector(supertypeInjector, userProvider);
  }
}

MainActivity_MembersInjector的create方法接收兩個(gè)參數(shù)挑围,生成一個(gè)實(shí)例返回。這個(gè)類實(shí)現(xiàn)了MembersInjector接口邓馒,實(shí)現(xiàn)了injectMembers方法轿塔,咦特愿?
instance.user = userProvider.get();
真相只有一個(gè),這一句才是真正執(zhí)行注入的代碼勾缭。從接收到的Provider實(shí)例中通過調(diào)用get方法拿到UserModel實(shí)例揍障,并賦給傳進(jìn)來(lái)的MainActivity實(shí)例的user成員變量。這也是為什么我們用 @Inject 注解的變量不可以是private的原因俩由。
所以這么看下來(lái)亚兄,注入過程還是很簡(jiǎn)單的,像很多文章說(shuō)的那樣采驻,There is no magic with Dagger.
就在飄飄然的時(shí)候,瞄見了這句代碼
supertypeInjector.injectMembers(instance);
supertypeInjector匈勋?這個(gè)是初始化的時(shí)候創(chuàng)建塞進(jìn)來(lái)的:

this.mainActivityMembersInjector = MainActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), provideUsersProvider);

注意這里有兩個(gè)長(zhǎng)得很像的類礼旅,MembersInjector 和 MembersInjectors,臥槽洽洁。
MembersInjector是一個(gè)接口痘系,就是上面提到的那個(gè),里面只有一個(gè)injectMembers抽象方法饿自。那MembersInjectors是什么鬼...

public final class MembersInjectors {
  /**
   * Returns a {@link MembersInjector} implementation that injects no members
   *
   * <p>Note that there is no verification that the type being injected does not have {@link Inject}
   * members, so care should be taken to ensure appropriate use.
   */
  @SuppressWarnings("unchecked")
  public static <T> MembersInjector<T> noOp() {
    return (MembersInjector<T>) NoOpMembersInjector.INSTANCE;
  }

  private static enum NoOpMembersInjector implements MembersInjector<Object> {
    INSTANCE;

    @Override public void injectMembers(Object instance) {
      if (instance == null) {
        throw new NullPointerException();
      }
    }
  }

  /**
   * Returns a {@link MembersInjector} that delegates to the {@link MembersInjector} of its
   * supertype.  This is useful for cases where a type is known not to have its own {@link Inject}
   * members, but must still inject members on its supertype(s).
   *
   * <p>Note that there is no verification that the type being injected does not have {@link Inject}
   * members, so care should be taken to ensure appropriate use.
   */
  @SuppressWarnings("unchecked")
  public static <T> MembersInjector<T> delegatingTo(MembersInjector<? super T> delegate) {
    return (MembersInjector<T>) delegate;
  }

  private MembersInjectors() {}
}

初始化中調(diào)用的noOp方法返回一個(gè)NoOpMembersInjector枚舉類汰翠,這個(gè)類同樣實(shí)現(xiàn)了MembersInjector接口龄坪,在injectMembers方法中check了instance是否為null。
什么鬼复唤,在注入前不是已經(jīng)check過了么:

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

這個(gè)鬼地方先按下不表健田,因?yàn)槲乙膊技獚u,回頭再看看回來(lái)補(bǔ)上佛纫,現(xiàn)在看不懂為什么要連著check兩次妓局。

除了上面這個(gè)問題,對(duì)于Dagger依賴注入的流程應(yīng)該是比較清晰的呈宇。首先build一個(gè)DaggerUserComponent實(shí)例好爬,把Module傳進(jìn)去,再調(diào)它的inject方法甥啄,DaggerUserComponent的inject方法會(huì)調(diào)到MainActivityMembersInjector的injectMembers方法存炮,在這里執(zhí)行真正的注入。

以上是依賴注入一個(gè)實(shí)例時(shí)Dagger生成的輔助代碼蜈漓。如果我們給兩個(gè)成員注入穆桂,如下:

public class MainActivity extends AppCompatActivity {

    @Inject
    UserModel user1;

    @Inject
    UserModel user2;

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

        DaggerUserComponent.builder()
                .userModule(new UserModule())
                .build()
                .inject(this);

        user2.setName("Arya Stark");
        user2.setAge(12);

        ((TextView) findViewById(R.id.text_view_1)).setText("Name:" + user1.getName() + "::Age:" + user1.getAge());
        ((TextView) findViewById(R.id.text_view_2)).setText("Name:" + user2.getName() + "::Age:" + user2.getAge());
    }
}

就不傳圖了,結(jié)果是兩個(gè)不一樣的TextView內(nèi)容迎变,因?yàn)檫@是兩個(gè)不同的實(shí)例充尉。
那么問題來(lái)了,那單例呢衣形?
還是用這個(gè)Sample驼侠,我給Component類和provide方法都加上 @Singleton 注解,最后的得到的結(jié)果就是單例谆吴,怎么做到的倒源?
對(duì)比了代碼后,我發(fā)現(xiàn)加Singleton注解和不加兩種情況下句狼,DaggerUserComponent的初始化代碼偷偷發(fā)生了變化笋熬。
不加 @Singleton 注解:

private void initialize(final Builder builder) {  
    this.provideUsersProvider = UserModule_ProvideUsersFactory.create(builder.userModule);
    this.mainActivityMembersInjector = MainActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), provideUsersProvider);
  }

加 @Singleton注解:

private void initialize(final Builder builder) {  
    this.provideUsersProvider = ScopedProvider.create(UserModule_ProvideUsersFactory.create(builder.userModule));
    this.mainActivityMembersInjector = MainActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), provideUsersProvider);
  }

看出區(qū)別了吧?不加注解的時(shí)候拿到的Provider是UserModule_ProvideUsersFactory的實(shí)例腻菇,加了注解后拿到的是ScopedProvider的實(shí)例胳螟。
好,來(lái)看看這個(gè)ScopedProvider.

/**
 * A {@link Provider} implementation that memoizes the result of a {@link Factory} instance.
 *
 * @author Gregory Kick
 * @since 2.0
 */
public final class ScopedProvider<T> implements Provider<T> {
  private static final Object UNINITIALIZED = new Object();

  private final Factory<T> factory;
  private volatile Object instance = UNINITIALIZED;

  private ScopedProvider(Factory<T> factory) {
    assert factory != null;
    this.factory = factory;
  }

  @SuppressWarnings("unchecked") // cast only happens when result comes from the factory
  @Override
  public T get() {
    // double-check idiom from EJ2: Item 71
    Object result = instance;
    if (result == UNINITIALIZED) {
      synchronized (this) {
        result = instance;
        if (result == UNINITIALIZED) {
          instance = result = factory.get();
        }
      }
    }
    return (T) result;
  }

  /** Returns a new scoped provider for the given factory. */
  public static <T> Provider<T> create(Factory<T> factory) {
    if (factory == null) {
      throw new NullPointerException();
    }
    return new ScopedProvider<T>(factory);
  }
}

其實(shí)所謂的ScopedProvider就是把Factory包了一層筹吐,在里面存儲(chǔ)了Factory的實(shí)例糖耸。當(dāng)我們調(diào)用inject時(shí),DaggerUserComponent會(huì)把調(diào)用轉(zhuǎn)發(fā)給Provider丘薛,此時(shí)也就是ScopedProvider的get方法嘉竟,單例的關(guān)鍵就在這里。
這個(gè)類里定義了一個(gè)靜態(tài)常量UNINITIALIZED,第一次進(jìn)入get方法時(shí),會(huì)把現(xiàn)在還是靜態(tài)常量的instance賦給result局部變量舍扰。然后進(jìn)入判斷倦蚪,拿鎖,從factory實(shí)例中取出UserModel實(shí)例边苹,賦給instance和result陵且,然后把result返回。此時(shí)勾给,instance變量已經(jīng)變成了我們之前拿到的那個(gè)UserModel實(shí)例了滩报。后面再進(jìn)來(lái),局部變量result(之前的UserModel實(shí)例)和靜態(tài)常量不等播急,就再也進(jìn)不去判斷脓钾,直接返回instance,也就實(shí)現(xiàn)了單例桩警。
但是注意可训,這個(gè)單例是存在于DaggerUserComponent的實(shí)例中的,也就是說(shuō)捶枢,如果DaggerUserComponent產(chǎn)生了新的實(shí)例握截,那么也會(huì)產(chǎn)生新的UserModel實(shí)例。不能光說(shuō)不練烂叔,來(lái)做個(gè)實(shí)驗(yàn)谨胞。
對(duì)MainActivity做以下更改:

public class MainActivity extends AppCompatActivity {

    @Inject
    UserModel user1;

    @Inject
    UserModel user2;

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

        DaggerUserComponent.builder()
                .userModule(new UserModule())
                .build()
                .inject(this);

        user2.setName("Arya Stark");
        user2.setAge(12);

        ((TextView) findViewById(R.id.text_view_1)).setText("Name:" + user1.getName() + "::Age:" + user1.getAge());
        ((TextView) findViewById(R.id.text_view_2)).setText("Name:" + user2.getName() + "::Age:" + user2.getAge());

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                DaggerUserComponent.builder()
                        .userModule(new UserModule())
                        .build()
                        .inject(MainActivity.this);
                ((TextView) findViewById(R.id.text_view_1)).setText("Name:" + user1.getName() + "::Age:" + user1.getAge());
                ((TextView) findViewById(R.id.text_view_2)).setText("Name:" + user2.getName() + "::Age:" + user2.getAge());
            }
        }, 2000);
    }
}

在第一次設(shè)置TextView的文字完了兩秒后,重新進(jìn)行一次注入蒜鸡,再更新TextView的顯示】枧現(xiàn)象就是,先顯示Arya Stark的信息逢防,兩秒后更新為十八歲的lala叶沛。因?yàn)榈诙巫⑷霑r(shí)生成了DaggerUserComponent的新實(shí)例,單例也就失效了忘朝。

自定義 @UserScope 注解
既然前面已經(jīng)把Dagger中的 @Singleton 的實(shí)現(xiàn)扒了個(gè)精光灰署,那么應(yīng)該很容易自定義Scope了。因?yàn)閱卫嬖谟赟copedProvider局嘁,而ScopedProvider是在Component中創(chuàng)建的溉箕,所以要自定義Scope,其實(shí)就是控制好Dagger給咱們生成的Component實(shí)現(xiàn)的生命周期悦昵。
哦對(duì)了约巷,先想想Scope是干啥的。我的理解是旱捧,保證某個(gè)類在一個(gè)時(shí)期中的實(shí)例的單一,也就是在定義的時(shí)期中是單例。比如我希望我們的CP項(xiàng)目Model在項(xiàng)目Activity中是單例枚赡,那么就可以定義一個(gè)ActivityScope氓癌,我希望我們的UserModel在用戶登陸后直到登出前是一個(gè)單例,那么就定義一個(gè)從登陸到登出的UserScope贫橙。
現(xiàn)在拓展一下我們的Sample. 在MainActivity之外贪婉,再創(chuàng)建SecondActivity和ThirdActivity,假設(shè)咱們的用戶在SecondActivity登錄卢肃,我們需要UserModel在SecondActivity到ThirdActivity之間是單例疲迂。
OK,既然UserScope跨Activity莫湘,那只能在比Activity更大的Scope下定義了尤蒿,這個(gè)Scope只能是整個(gè)App的ApplicationScope。
好吧幅垮,咱們還是按流程來(lái)腰池。先為整個(gè)App定義最大的Component:

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

    UserComponent plus(UserModule userModule);

}

注解里標(biāo)識(shí)的AppModule:

@Module
public class AppModule {

    private Application application;

    public AppModule(Application application) {
        this.application = application;
    }

    @Provides
    public Application provideApplication() {
        return application;
    }

}

然后添加兩個(gè)Activity,SecondActivity和ThirdActivity忙芒,并為他們分別添加Component和Module示弓,代碼就不貼了。
這里咱們要用到一個(gè)叫做@Subcomponent的注解呵萨,它標(biāo)識(shí)子Component在父Component下進(jìn)行實(shí)現(xiàn)奏属,后面看了源碼就明白了,先記著潮峦。

@Subcomponent(modules = {SecondActivityModule.class})
public interface SecondActivityComponent {
    SecondActivity inject(SecondActivity secondActivity);
}
@Subcomponent(modules = {ThirdActivityModule.class})
public interface ThirdActivityComponent {
    ThirdActivity inject(ThirdActivity thirdActivity);
}

這兩個(gè)子Component的接口在inject方法中接收一個(gè)自己的Activity囱皿,然后返回去。
之后跑杭,添加一個(gè)Application的子類:

public class DaggerDemoApplication extends Application {

    private AppComponent appComponent;
    private UserComponent userComponent;

    public static DaggerDemoApplication get(Context context) {
        return (DaggerDemoApplication) context.getApplicationContext();
    }

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

    private void initAppComponent() {
        appComponent = DaggerAppComponent.builder()
                .appModule(new AppModule(this))
                .build();
    }

    public UserComponent createUserComponent() {
        userComponent = appComponent.plus(new UserModule());
        return userComponent;
    }

    public void destroyUserComponent() {
        userComponent = null;
    }

    public AppComponent getAppComponent() {
        return appComponent;
    }

    public UserComponent getUserComponent() {
        return userComponent;
    }
}

注意铆帽,要在Manifest里頭為Application標(biāo)簽加上name屬性,name設(shè)為這個(gè)類名德谅。這樣爹橱,這個(gè)類就會(huì)在整個(gè)App啟動(dòng)的時(shí)候率先執(zhí)行。
就像前面說(shuō)的窄做,因?yàn)閁serScope跨Activity愧驱,所以要把它存在AppScope里頭,也就是說(shuō)當(dāng)UserScope開始時(shí)創(chuàng)建UserComponent的實(shí)現(xiàn)并存起來(lái)椭盏,當(dāng)UserScope結(jié)束的時(shí)候组砚,把UserComponent的實(shí)例釋放。所以在這里有create和destroy兩個(gè)方法掏颊,用于控制UserComponent的生命周期糟红。
創(chuàng)建UserScope注解:

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

現(xiàn)在更改一下Activity的內(nèi)容艾帐,把MainActivity的內(nèi)容更換成一個(gè)按鈕,用于開啟SecondActivity盆偿,在SecondActivity上添加兩個(gè)TextView和一個(gè)按鈕用于開啟ThirdActivity柒爸,ThirdActivity只有兩個(gè)TextView。
MainActivity:

public class MainActivity extends AppCompatActivity {

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

        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivity(new Intent(MainActivity.this, SecondActivity.class));
            }
        });
    }
}
public class SecondActivity extends AppCompatActivity {

    @Inject
    UserModel user;

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

        DaggerDemoApplication.get(this)
                .getUserComponent()
                .plus(new SecondActivityModule())
                .inject(this);

        user.setName("Arya");
        user.setAge(12);
        ((TextView) findViewById(R.id.text_view)).setText("Name:" + user.getName() + ":::Age:" + user.getAge());

        findViewById(R.id.button_second).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivity(new Intent(SecondActivity.this, ThirdActivity.class));
            }
        });
    }

    @Override
    public void finish() {
        DaggerDemoApplication.get(this).destroyUserComponent();
        super.finish();
    }
}
public class ThirdActivity extends AppCompatActivity {

    @Inject
    UserModel user;

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

        DaggerDemoApplication.get(this)
                .getUserComponent()
                .plus(new ThirdActivityModule())
                .inject(this);

        ((TextView) findViewById(R.id.text_view)).setText("Name:" + user.getName() + ":::Age:" + user.getAge());
    }
}

運(yùn)行一下事扭。


Screenshot_2017-02-09-09-48-06.png

Screenshot_2017-02-09-09-48-10.png

Screenshot_2017-02-09-09-48-14.png

可以看到捎稚,我在SecondActivity和ThirdActivity分別進(jìn)行了一次注入,只在SecondActivity更改了user的值求橄,結(jié)果在ThirdActivity中也生效了今野,說(shuō)明這個(gè)UserModel實(shí)例在SecondActivity和ThirdActivity之間是單例的存在。
下面咱來(lái)看看Dagger為咱們生成的代碼是怎么做到的罐农。

與之前不同条霜,Dagger在這里并沒有生成UserComponent實(shí)現(xiàn)的單獨(dú)類,而是將它作為DaggerAppComponent的內(nèi)部類啃匿。

@Generated("dagger.internal.codegen.ComponentProcessor")
public final class DaggerAppComponent implements AppComponent {
  private DaggerAppComponent(Builder builder) {  
    assert builder != null;
  }

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

  @Override
  public UserComponent plus(UserModule userModule) {  
    return new UserComponentImpl(userModule);
  }

  public static final class Builder {
    private AppModule appModule;
  
    private Builder() {  
    }
  
    public AppComponent build() {  
      if (appModule == null) {
        throw new IllegalStateException("appModule must be set");
      }
      return new DaggerAppComponent(this);
    }
  
    public Builder appModule(AppModule appModule) {  
      if (appModule == null) {
        throw new NullPointerException("appModule");
      }
      this.appModule = appModule;
      return this;
    }
  }

  private final class UserComponentImpl implements UserComponent {
    private final UserModule userModule;
    private Provider<UserModel> provideUsersProvider;
  
    private UserComponentImpl(UserModule userModule) {  
      if (userModule == null) {
        throw new NullPointerException();
      }
      this.userModule = userModule;
      initialize();
    }
  
    private void initialize() {  
      this.provideUsersProvider = ScopedProvider.create(UserModule_ProvideUsersFactory.create(userModule));
    }
  
    @Override
    public SecondActivityComponent plus(SecondActivityModule secondActivityModule) {  
      return new SecondActivityComponentImpl(secondActivityModule);
    }
  
    @Override
    public ThirdActivityComponent plus(ThirdActivityModule thirdActivityModule) {  
      return new ThirdActivityComponentImpl(thirdActivityModule);
    }
  
    private final class SecondActivityComponentImpl implements SecondActivityComponent {
      private final SecondActivityModule secondActivityModule;
      private MembersInjector<SecondActivity> secondActivityMembersInjector;
    
      private SecondActivityComponentImpl(SecondActivityModule secondActivityModule) {  
        if (secondActivityModule == null) {
          throw new NullPointerException();
        }
        this.secondActivityModule = secondActivityModule;
        initialize();
      }
    
      private void initialize() {  
        this.secondActivityMembersInjector = SecondActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), UserComponentImpl.this.provideUsersProvider);
      }
    
      @Override
      public SecondActivity inject(SecondActivity secondActivity) {  
        secondActivityMembersInjector.injectMembers(secondActivity);
        return secondActivity;
      }
    }
  
    private final class ThirdActivityComponentImpl implements ThirdActivityComponent {
      private final ThirdActivityModule thirdActivityModule;
      private MembersInjector<ThirdActivity> thirdActivityMembersInjector;
    
      private ThirdActivityComponentImpl(ThirdActivityModule thirdActivityModule) {  
        if (thirdActivityModule == null) {
          throw new NullPointerException();
        }
        this.thirdActivityModule = thirdActivityModule;
        initialize();
      }
    
      private void initialize() {  
        this.thirdActivityMembersInjector = ThirdActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), UserComponentImpl.this.provideUsersProvider);
      }
    
      @Override
      public ThirdActivity inject(ThirdActivity thirdActivity) {  
        thirdActivityMembersInjector.injectMembers(thirdActivity);
        return thirdActivity;
      }
    }
  }
}

這個(gè)類相對(duì)比較長(zhǎng)蛔外,但是也不難理解∷萜梗可以看一眼我們是如何在DaggerDemoApplication中創(chuàng)建AppComponent和UserComponent的實(shí)現(xiàn)的夹厌。

private void initAppComponent() {
        appComponent = DaggerAppComponent.builder()
                .appModule(new AppModule(this))
                .build();
    }

    public UserComponent createUserComponent() {
        userComponent = appComponent.plus(new UserModule());
        return userComponent;
    }

父Component AppComponent實(shí)現(xiàn)的創(chuàng)建與之前無(wú)異,使用它的Builder裆悄,傳一個(gè)AppModule實(shí)例再build矛纹。而作為子Component的UserComponent的創(chuàng)建就不同了。這里調(diào)用AppComponent的plus方法光稼,這個(gè)方法是我們定義的接口或南,接收一個(gè)UserModule實(shí)例,返回UserComponent.
在我們調(diào)用plus的時(shí)候艾君,創(chuàng)建了UserComponentImpl實(shí)例并返回采够。在這個(gè)內(nèi)部類中也有兩個(gè)我們定義的接口方法,分別接收自己Activity的Module冰垄,然后返回自己Activity的Component蹬癌,在這里又分別創(chuàng)建了SecondActivityComponentImpl和ThirdActivityComponentImpl實(shí)例。
再進(jìn)到這兩個(gè)內(nèi)部類中可以看到虹茶,真正的注入方法在這里逝薪。

@Override
      public SecondActivity inject(SecondActivity secondActivity) {  
        secondActivityMembersInjector.injectMembers(secondActivity);
        return secondActivity;
      }

注意,這里的secondActivityMembersInjector在SecondActivityComponentImpl的初始化方法中創(chuàng)建:

private void initialize() {  
        this.secondActivityMembersInjector = SecondActivity_MembersInjector.create((MembersInjector) MembersInjectors.noOp(), UserComponentImpl.this.provideUsersProvider);
      } 

而provider是在UserComponentImpl中的初始化方法中創(chuàng)建的:

private void initialize() {  
      this.provideUsersProvider = ScopedProvider.create(UserModule_ProvideUsersFactory.create(userModule));
    }

剩下的注入流程和之前的就一樣了蝴罪。inject方法中調(diào)用SecondActivity_MembersInjector的injectMembers方法董济,在這里通過調(diào)用Provider的get方法,由provider決定是否需要新建實(shí)例要门,需要時(shí)再調(diào)到咱們的provide方法拿到真正的實(shí)例并返回虏肾,不需要時(shí)直接返回廓啊。
以上是對(duì)使用 @SubComponent 注解實(shí)現(xiàn)自定義Scope的源碼解析。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末询微,一起剝皮案震驚了整個(gè)濱河市崖瞭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌撑毛,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件唧领,死亡現(xiàn)場(chǎng)離奇詭異藻雌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)斩个,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門胯杭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人受啥,你說(shuō)我怎么就攤上這事做个。” “怎么了滚局?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵居暖,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我藤肢,道長(zhǎng)太闺,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任嘁圈,我火速辦了婚禮省骂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘最住。我一直安慰自己钞澳,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布涨缚。 她就那樣靜靜地躺著轧粟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪仗岖。 梳的紋絲不亂的頭發(fā)上逃延,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音轧拄,去河邊找鬼揽祥。 笑死,一個(gè)胖子當(dāng)著我的面吹牛檩电,可吹牛的內(nèi)容都是我干的拄丰。 我是一名探鬼主播府树,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼料按!你這毒婦竟也來(lái)了奄侠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤载矿,失蹤者是張志新(化名)和其女友劉穎垄潮,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體闷盔,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡弯洗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了逢勾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片牡整。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖溺拱,靈堂內(nèi)的尸體忽然破棺而出逃贝,到底是詐尸還是另有隱情,我是刑警寧澤迫摔,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布沐扳,位于F島的核電站,受9級(jí)特大地震影響攒菠,放射性物質(zhì)發(fā)生泄漏迫皱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一辖众、第九天 我趴在偏房一處隱蔽的房頂上張望卓起。 院中可真熱鬧,春花似錦凹炸、人聲如沸戏阅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)奕筐。三九已至,卻和暖如春变骡,著一層夾襖步出監(jiān)牢的瞬間离赫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工塌碌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留渊胸,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓台妆,卻偏偏與公主長(zhǎng)得像翎猛,于是被迫代替她去往敵國(guó)和親胖翰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容