Dagger2 (1)

Dagger 2 有什么用?
android 中我们创建一个对象,往往是有着一大堆其他的依赖关系的,我就想要个A类,不好意思你得先提供B类和C类的实例参数。所以常常见到一个Activity中为了得到一个实例,前面个一大堆其他的对象获取,更烦的是偶尔可能某个类发生变动,这个时候跟这个类有关系的类也要跟着全部变动。基于这些场景,为了尽可能的降低耦合,削弱类之间的依赖关系带来的代码不易维护等后果,就产生了一些注解框架。

至于为什么用dagger2 ?

Dagger 2 analyzes these dependencies for you and generates code to help wire them together. While there are other Java dependency injection frameworks, many of them suffered limitations in relying on XML, required validating dependency issues at run-time, or incurred performance penalties during startup. Dagger 2 relies purely on using Java annotation processorsand compile-time checks to analyze and verify dependencies. It is considered to be one of the most efficient dependency injection frameworks built to date.

看了一下dagger2,就蛮记录一下。

@Inject @Component @Provides @Module。(基础几个的注解)

怎么说呢,这几个东西之间的关系就像,酒楼里面的关系。
@inject 就是客人需要的食品,
@Component 就是小二,
@Module就是仓库(囤着食材的地方)
@Provides 就是仓库里面的食材。

1.客人(Mainactivity)说:给老子来条烤鱼!(Fish 不能设置为private)

public class MainActivity extends AppCompatActivity {
    @Inject
    Fish fish; 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

2.这个时候酒楼就会去找打被打上@inject的那条烤鱼。(如果多个重载方法,只能其中一个标注)

public class Fish {
    private Vegetables vegetables;
    private Fruit fruit;
    @Inject
    Fish(Vegetables vegetables, Fruit fruit) {
        this.vegetables = vegetables;
        this.fruit = fruit;
    }
    public  String getMaterialName(){
      return vegetables.getName()+"-->"+ fruit.getName();
    }
}

3 然后酒楼一看我靠这条鱼还要两个食材搭配,就会进到仓库@Module去寻找被打上@Provides并且是烤鱼需要的食材。
3.1 如果没有参数,也就是不需要其他配料那就不用到仓库了也就是不用@Module、@Provides。

public class Apple extends Fruit {
    @Override
    public String getName() {
        return "苹果嘛";
    }
}

public class Lettuce extends Vegetables {
    @Override
    public String getName() {
        return "生菜啊";
    }
}

@Module
public class FruitModule {
    @Provides
    public Fruit getApple() {
        return new Apple();
    }
}
@Module
public class VegetablesModule  {
    @Provides
    public Vegetables getLettuce() {
        return new Lettuce();
    }
}

3.2 如果酒楼压根就找不到这种鱼(鱼是来自第三方类库,我们无法对他的构造函数打上@Inject),这个时候?

3.2.1.新建鱼仓库:

@Module
public class FishModule {
    @Provides
    public Fish getFish(Vegetables vegetables, @FruitApple Fruit fruit){
        return new Fish(vegetables,fruit);
    }
}

3.2.2
FishComponent 需要多指定一个FishModule或者改用dependencies 也可以。

@Component(modules ={FishModule.class,FruitModule.class,VegetablesModule.class})
public interface FishComponent {
   //将实例注入目标
   void inject(MainActivity mainActivity);
}

4 酒楼拿着提供的两样食材之后,做好烤鱼后,小二@Component 将烤鱼送上。

@Component(modules ={FruitModule.class,VegetablesModule.class})
public interface FishComponent {
   //自定义注入方法,将实例注入目标 (注入目标要有)
   void inject(MainActivity mainActivity);
}

4 .动手解决(写这段代码前先rebuild 一下。DaggerFishComponent 是自动生成的 -->Dagger+你的component类名)

public class MainActivity extends AppCompatActivity {
    @Inject
    Fish fish;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //FruitModule 为无参构造函数时可用
        DaggerFishComponent.create().inject(this);
        //FruitModule 为有参构造函数时用
       // //DaggerFishComponent.builder().fruitModule(new FruitModule()).build().inject(this);
          Log.e("MainActivity","result is---->"+fish.getMaterialName());//生菜啊-->苹果嘛
        //结果说明Fish是注入的,并且打出结果。
        
    }
}

仅仅打了几个注解,鱼到底怎么生成的?

思路应该也是差不多,要得到这条鱼肯定得提供两个配菜。看下生成的代码:

}L2W@ZIP)LABT_P%)%V_E6U.png

@Provides 会生成对应的提供类。所以有FruitModule_GetAppleFactory、VegetablesModule_GetLettuceFactory 。假如FruitModule 还有其他的@Provides 就还会生成FruitModule_XXXFactory。

FruitModule_GetAppleFactory :可以看到我们可以通过creat获取该实例,然后get一apple对象(该类重写了Factory<T>的上层接口Provider<T>的get方法用于返回一个apple对象)。 /
VegetablesModule_GetLettuceFactory 也是一样的方式。@Inject 生成的Fish_Factor也是差不多。

public final class FruitModule_GetAppleFactory implements Factory<Fruit> {
  private final FruitModule module;

  public FruitModule_GetAppleFactory(FruitModule module) {
    assert module != null;
    this.module = module;
  }

  @Override
  public Fruit get() {
    return Preconditions.checkNotNull(
        module.getApple(), "Cannot return null from a non-@Nullable @Provides method");
  }

  public static Factory<Fruit> create(FruitModule module) {
    return new FruitModule_GetAppleFactory(module);
  }
}

这样鱼的材料凑齐,可以看到在@Component 生成的DaggerFishComponent类中,该类实现了FishComponent的inject。在我们调用build或者create(无参数module可用create)之后实现Fish的注入。

public final class DaggerFishComponent implements FishComponent {
  private Provider<Vegetables> getLettuceProvider;

  private Provider<Fruit> getAppleProvider;

  private Provider<Fish> fishProvider;

  private MembersInjector<MainActivity> mainActivityMembersInjector;

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

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

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

  @SuppressWarnings("unchecked")
  private void initialize(final Builder builder) {

    this.getLettuceProvider = VegetablesModule_GetLettuceFactory.create(builder.vegetablesModule);

    this.getAppleProvider = FruitModule_GetAppleFactory.create(builder.fruitModule);

    this.fishProvider = Fish_Factory.create(getLettuceProvider, getAppleProvider);

    this.mainActivityMembersInjector = MainActivity_MembersInjector.create(fishProvider);
  }

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

  public static final class Builder {
    private VegetablesModule vegetablesModule;

    private FruitModule fruitModule;

    private Builder() {}

    public FishComponent build() {
      if (vegetablesModule == null) {
        this.vegetablesModule = new VegetablesModule();
      }
      if (fruitModule == null) {
        this.fruitModule = new FruitModule();
      }
      return new DaggerFishComponent(this);
    }

    public Builder fruitModule(FruitModule fruitModule) {
      this.fruitModule = Preconditions.checkNotNull(fruitModule);
      return this;
    }

    public Builder vegetablesModule(VegetablesModule vegetablesModule) {
      this.vegetablesModule = Preconditions.checkNotNull(vegetablesModule);
      return this;
    }
  }
}

补:谷歌的官方示例中 @inject 也是可以注解方法的。(依赖this的时候,可以提供安全的this对象,他是在构造函数之后执行的)

JE7VGS_S70HR_ADAF{WG2RT.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容