依赖注入
使用
ButterKnife
在setContentView(..);之后加入ButterKnife.bind(this),
@BindView(R.id.testFre)SimpleDraweeView testFre;
@BindView(R.id.test)TextView test;
Dagger2:
场景:想在一个类中使用新建另外一个类,但是又觉得显示创建耦合性太高,所以使用Dagger。其实Dagger的使用是比较简单的,主要在需要新建一个类和一个接口:
1、新建Module类:
@Module
public class DemoModule {
@Provides
Person providePerson(){//声明需要依赖注入的类,方法名可以是任意的
return new Person();
}
}
2、新建Component接口:
@Component(modules=DemoModule.class)
public interface DemoComponent {
void inject(Dagger2Activity activity);//设置需要在那个类里进行依赖注入,也就是声明宿主
Person getPerson();//这是依赖注入的第二种方法,一般用在全局设置中,如框架整合
}
3、两种形式的使用,请注意区别:
第一种实现
public class Dagger2Activity extends AppCompatActivity {
@Inject
Person person;//使用@Inject在宿主Dagger2Activity中依赖注入Person,
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dagger2);
//特别注意DaggerCarComponent是Dagger2自动生成的,需要reBuild或者Make Project生成
DemoComponent component = DaggerDemoComponent.builder().build();
//进行注入
component.inject(this);
Log.i("111",person.toString());
}
}
第二种实现
public class Dagger2Activity extends AppCompatActivity {
Person person;//第二种实现
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dagger2);
//特别注意DaggerCarComponent是Dagger2自动生成的,需要reBuild或者Make Project生成
DemoComponent component = DaggerDemoComponent.builder().build();
//进行注入
component.inject(this);
person=component.getPerson();
Log.i("111",person.toString());
}
}
需要注意的是Dagger2主要进行模块间的解耦,这里是最简单的使用demo。一般来说会配合MVP设计模式,以及一些其他的网络或者图片框架(Retrofit,RxAndroid,glide,Gson)使用,这些整合并不冲突。
MVP+Dagger2:这里假设已经已经搭好了简单的MVP架构。
1、新建一个Module类和Component接口
@Module
public class UserModule {
private final IUserView view ;
public UserModule(IUserView view){
this.view = view ;
}
@Provides
IUserView provideILogView(){
return view;//注意这里选择使用IUserView作为依赖注入对象
}
}
@Component(modules = UserModule.class)
public interface UserComponent {
public void inject(MvpActivity activity);
}
2、修改Presenter中的代码:
public class UserPresenter {
private IUserView mUserView;
private IUserModel mUserModel;
//修改前代码
public UserPresenter(IUserView view) {
mUserView = view;
mUserModel = new UserModelImpl();
}
//修改后代码
@Inject
public UserPresenter(IUserView view) {
mUserView = view;
mUserModel = new UserModelImpl();
Log.i("xixi","依赖注入了presenter");
}
public void saveUser( int id, String name) {
mUserModel.getID();
}
public void loadUser( int id) {
UserBean user = mUserModel.load(id);
mUserView.setName(user.getName()); // 通过调用IUserView的方法来更新显示
}
}
3、修改宿主类:
@Inject
UserPresenter mUserPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mvp);
//mUserPresenter = new UserPresenter( this);
DaggerUserComponent.builder().userModule(new UserModule(this)).build().inject(this);
}
完成完成
MVP+Dagger2+Retrofit+RxAndroid+glide+Gson:
在MVp+Dagger2的基础上,可以进一步的将一些框架封装进来。大体思路如下:
1、将这些框架封装成一个完整的只暴露接口的类;
2、将这些类进一步封装到module中:
@Module
public class RetrofitModule {
@Provides
public OkHttpClient provideOkHttpClient() {
OkHttpClient okHttpClient = new OkHttpClient();
//okHttpClient.setConnectTimeout(60 * 1000, TimeUnit.MILLISECONDS);
//okHttpClient.setReadTimeout(60 * 1000, TimeUnit.MILLISECONDS);
return okHttpClient;
}
@Provides
public Retrofit provideRetrofit(Application application, OkHttpClient okHttpClient){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("")
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 添加Rx适配器
.addConverterFactory(GsonConverterFactory.create()) // 添加Gson转换器
.client(okHttpClient)
.build();
return retrofit;
}
@Provides
protected HttpService provideGitHubService(Retrofit retrofit) {
return retrofit.create(HttpService.class);
}
}
HttpService代码如下:
public interface HttpService {
@POST("test/{id}")
Observable<UserBean> getData(@Path("id") int id);
}
3、将这些module都封装到一个全局的AppComponent类中。
@Singleton
@Component(modules = {RetrofitModule.class, GlideServiceModule.class})
public interface AppComponent {
HttpService getService();
GlideService getImageLoader();
}
4、使用
Bufferknife
视图类以及资源的注入。
利用反射和注解。
@NonNull @UiThread
public static Unbinder bind(@NonNull Activity target) {
View sourceView = target.getWindow().getDecorView();
return createBinding(target, sourceView);
}
其中sourceView是顶级装饰view,进一步追踪createBinding(target, sourceView)
private static Unbinder createBinding(@NonNull Object target, @NonNull View source) {
Class<?> targetClass = target.getClass();
if (debug) Log.d(TAG, "Looking up binding for " + targetClass.getName());
//核心方法1,返回一个Constructor
Constructor<? extends Unbinder> constructor = findBindingConstructorForClass(targetClass);
if (constructor == null) {
return Unbinder.EMPTY;
}
//noinspection TryWithIdenticalCatches Resolves to API 19+ only type.
try {
//核心方法2
return constructor.newInstance(target, source);
} catch (IllegalAccessException e) {
throw new RuntimeException("Unable to invoke " + constructor, e);
} catch (InstantiationException e) {
throw new RuntimeException("Unable to invoke " + constructor, e);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
}
if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException("Unable to create binding instance.", cause);
}
}
Dagger2
@Inject
@Module
@Provides
@Component(modules = HttpHelperModule.class)
未完待续。
注意
ButterKnife和Dagger2是有冲突的,