上一篇介绍了Dagger2的一些注解点击打开链接
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
2.在build.gradle(Module:app)中添加如下代码,应用apt插件
apply plugin: 'com.neenbedankt.android-apt'
...
dependencies {
provided 'org.glassfish:javax.annotation:10.0-b28'
compile 'com.google.dagger:dagger:2.5'
compile 'com.google.dagger:dagger-compiler:2.5'
}
dragger2引入是会出现一些问题,配置这些即可
dexOptions {
javaMaxHeapSize "4g"
}
defaultConfig {
...
multiDexEnabled true
}
3.关于dagger2与Retrofit2之间分包的问题
multiDexEnabled true设置为true会导致找不到Retrofit
如果关闭,又会报 64K什么的 方法错误
解决办法
compile 'com.android.support:multidex:1.0.1'
如果继承了Application
还需重写
/**
* 分割 Dex 支持
* @param base
*/
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
public class Food { @Inject public Food() { } public String eated(){ return "吃东西!!!"; } }
public class Person { public Food food; @Inject public Person(Food food) { this.food = food; } public String eat(){ return food.eated(); } }Component作为桥梁,将MainActivity与Food连接
@Component public interface FoodComponent { void inject(MainActivity mainActivity); }
public class MainActivity extends AppCompatActivity { @Bind(R.id.info) TextView info; @Inject Person person; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); DaggerFoodComponent.builder() .build().inject(this); info.setText(person.eat()); } }DaggerFoodComponent.builder().build().inject(this);实现依赖注入。上源码吧,不然说不清了 - -。。。
public final class DaggerFoodComponent implements FoodComponent { private ProviderFood工厂和Person工厂源码personProvider; private MembersInjector mainActivityMembersInjector; private DaggerFoodComponent(Builder builder) { assert builder != null; initialize(builder);//3---->build方法会调用initialize方法 } public static Builder builder() { //1-------->先在这里被调用 return new Builder(); } public static FoodComponent create() { return builder().build(); } @SuppressWarnings("unchecked") private void initialize(final Builder builder) {//4------>这个方法会实例化内部属性,通过简单工厂就生成了一个对象 this.personProvider = Person_Factory.create(Food_Factory.create());//这里你会发现personProvider对象被实例化了,但是里面还有一个FoodProvider对象,再看看我们的实体类,里面确实有一个FoodProvider,所以我们有需要通过Food工厂获得foodProvider对象,Factory继承自Provider this.mainActivityMembersInjector = MainActivity_MembersInjector.create(personProvider);//这里就是初始化MembersInjector这个对象 } @Override public void inject(MainActivity mainActivity) {//-5----->最后将实例化好的对象注入到Activity/class/Fragment mainActivityMembersInjector.injectMembers(mainActivity);//6---->而这个方法(针对我们当前示例)就是把activity中的person对象实例化了 } public static final class Builder { private Builder() {} public FoodComponent build() {//2--------->调用build方法 return new DaggerFoodComponent(this); } } }
public enum Food_Factory implements Factory{ INSTANCE; @Override public Food get() { return new Food(); } public static Factory create() { return INSTANCE; } }
public final class Person_Factory implements Factory{ private final Provider foodProvider; public Person_Factory(Provider foodProvider) { assert foodProvider != null; this.foodProvider = foodProvider; } @Override public Person get() { return new Person(foodProvider.get()); } public static Factory create(Provider foodProvider) { return new Person_Factory(foodProvider); } }
public final class MainActivity_MembersInjector implements MembersInjector{ private final Provider //7----->通过Factory的get方法获得实例,赋值给当前activity中的person。 if(instance == null) { throw new NullPointerException("Cannot inject members into a null reference"); } else { instance.person = (Person)this.personProvider.get(); } } public static void injectPerson(MainActivity instance, ProviderpersonProvider; public MainActivity_MembersInjector(Provider personProvider) { assert personProvider != null; this.personProvider = personProvider; } public static MembersInjector create(Provider personProvider) { return new MainActivity_MembersInjector(personProvider); } public void injectMembers(MainActivity instance) { personProvider) { instance.person = (Person)personProvider.get() ; } }
@Module public class FoodModule { @Provides public Food provideFood(){ return new Food(); } @Provides public Person providePerson(Food food){ return new Person(food); } }这里的Component接口中就需要声明是那个或哪些modules为Activity提供依赖
@Component(modules = {FoodModule.class}) public interface FoodComponent { void inject(MainActivity mainActivity); }
@Module public class FoodModule { @Provides public Person providePerson(Food food){ return new Person(food); } @Person1 @Provides Person providePerson2(Food food){ return new Person(food); } }
@Inject Person person; @Person1 @Inject Person person1;这样就能避免依赖方法不知给谁提供依赖了。
@Module public class AppModule { private Context context; public AppModule(App app) { this.context = app; } @Singleton @Provides public Context providerApplicationContext() { return this.context; } @Singleton @Provides public OkHttpClient provideClient() { OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(5, TimeUnit.SECONDS) .readTimeout(5, TimeUnit.SECONDS) .build(); return client; } @Singleton @Provides public Retrofit provideRetrofit(OkHttpClient client){ Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://127.0.0.1:8080/") .addConverterFactory(GsonConverterFactory.create(new Gson())) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .client(client) .build(); return retrofit; } }用Singleton标注视情况而定,如果你要保证它是唯一的,那么就用Singleton标注。
@Singleton @Component(modules = {AppModule.class}) public interface AppComponent { OkHttpClient getClient(); Retrofit getRetrofit(); }用Singleton标注,说明它是全局的单例
@ActivityScope @Component(modules = {FoodModule.class},dependencies = {AppComponent.class}) public interface FoodComponent { void inject(MainActivity mainActivity); }Activity中的代码
@Bind(R.id.info) TextView info; @Named("1") @Inject Person person; @Inject Retrofit retrofit; @Inject OkHttpClient client; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); DaggerFoodComponent.builder().appComponent(App.get(this).getAppComponent()) .foodModule(new FoodModule()) .build() .inject(this); info.setText(person.eat()+"\nretrofit="+retrofit.toString()); }
当然改成SubComponent也不难,只需要改Component即可。
@Singleton @Component(modules = {AppModule.class}) public interface AppComponent { FoodComponent addSub(FoodModule foodModule); OkHttpClient getClient(); Retrofit getRetrofit(); }
@ActivityScope //@Component(modules = {FoodModule.class},dependencies = {AppComponent.class}) @Subcomponent(modules = {FoodModule.class}) public interface FoodComponent { void inject(MainActivity mainActivity); }
App.get(this).getAppComponent().addSub(new FoodModule()).inject(this);
@Named("1") @Inject Lazyperson; Person p = person.get(); info.setText(p.eat()+"\nretrofit="+retrofit.toString());