Android之dagger2的简单运用和详细解读(入门)
2016-09-14 23:46
519 查看
dagger2的使用和理解
dagger2的使用,给程序带来了非常好的解耦,废话不多说,直接开始基本的配置:
在project根目录build.gradle添加
dependencies { classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4' }
在module 的build.gradle添加
apply plugin: 'com.neenbedankt.android-apt' dependencies { ... compile 'com.google.dagger:dagger:2.0' apt 'com.google.dagger:dagger-compiler:2.0' compile 'org.glassfish:javax.annotation:10.0-b28' // Java标注 }
注意:
1.使用@Inject时,不能用private修饰符修饰类的成员属性。
2.项目中同时用了Butterknife,需要在module build.gradle添加
packagingOptions { exclude 'META-INF/services/javax.annotation.processing.Processor' }
3.使用@Scope注解的Component不能被没有使用其注解的Component所依赖。
一:dagger2在android中依赖注入代码实现
这是我之前一个项目关于dagger2的相关代码,具体里面的内容不用管,我们只需要关注每个@provides方法的传入参数以及返回结果就可以。每一行代码都注释得很清楚,相信大家读完,基本的流程也就明白了。
1.建立接口component,表示连接器,并且用注解Component标记,如果有Module,可以在引入。(Component是连接@Module和@Inject的桥梁)
@Singleton @Component(modules = {ApplicationMoudle.class, ApiMoudle.class}) public interface ApplicationComponent { Context getContext();//对外暴露Context ,这个context由ApplicationMoudle提供 //对外暴露OkHttpHelper,这个context由ApplicationMoudle提供 OkHttpHelper getOkHttpHelper(); //对外暴露UserStorage ,这个context由ApplicationMoudle提供 UserStorage getUserStorage(); //对外暴露UserApi ,这个context由ApiMoudle提供 UserApi getUserApi(); //对外暴露TicketApi ,这个context由ApiMoudle提供 TicketApi getTicketApi(); //要注入到MyApplication void inject(MyApplication application); }
2.创建类module一个或多个,并且用注解@Module标记。
@Provides 表示对外提供
@Singleton 表示单例,对象只会被初始化一次,之后的每次都会被直接注入相同的对象
@Named 表示
@Module public class ApplicationMoudle { private Context context; //构造方法会在创建component的时候,手动去new创建,并且传入context,和普通对象是一模一样的 public ApplicationMoudle(Context context){ this.context = context; } //向外提供Context @Provides @Singleton public Context provideApplicationContext(){ return context; } //向外提供OkHttpClient ,并且用@Named(“api”)做标记,因为这个Module里面有两个提供OkHttpClient 的方法,需要区分。 @Provides @Singleton @Named("api") OkHttpClient provideApiOkHttpClient(){ OkHttpClient.Builder builder = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS) .writeTimeout(10, TimeUnit.SECONDS); HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); builder.addInterceptor(loggingInterceptor); return builder.build(); } //向外提供OkHttpClient ,这个参数OkHttpClient 从上一个标记了@Named("api") 方法提供而来。 @Provides @Singleton OkHttpClient provideOkHttpClient(@Named("api") OkHttpClient mOkHttpClient) { OkHttpClient.Builder builder = mOkHttpClient.newBuilder() .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .retryOnConnectionFailure(true); builder.interceptors().clear(); return builder.build(); } //向外提供LayoutInflater @Provides @Singleton LayoutInflater provideLayoutInflater(Context context) { return (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } //向外提供UserStorage @Provides @Singleton UserStorage proviceUserStorage(Context mContext){ return new UserStorage(mContext); } //向外提供RequestHelper,参数UserStorage 由proviceUserStorage方法提供而来。 @Provides @Singleton RequestHelper proviceRequestHelper(Context mContext,UserStorage mUserStorage){ return new RequestHelper(mContext,mUserStorage); } //向外提供OkHttpHelper ,参数OkHttpClient 由provideOkHttpClient()方法提供而来。 @Provides @Singleton OkHttpHelper provideOkHttpHelper(OkHttpClient mOkHttpClient) { return new OkHttpHelper(mOkHttpClient); } } @Module public class ApiMoudle { //向外提供UserApi ,参数OkHttpClient 由ApplicationModule的提供方法provideOkHttpClient()提供而来。 @Provides @Singleton public UserApi proviceUserApi(@Named("api") OkHttpClient okHttpClient){ return new UserApi(okHttpClient); } //向外提供TicketApi ,参数OkHttpClient 由ApplicationModule的提供方法provideOkHttpClient()提供而来。 @Provides @Singleton public TicketApi proviceTicketApi(@Named("api") OkHttpClient okHttpClient){ return new TicketApi(okHttpClient); } }
可以发现,每一个提供出去的对象,又可以为其他的提供方法提供参数,也为@inject标注的构造函数提供参数。
总而言之:
如果@Provides方法有参数,这个参数需要通过其他的@Provides方法或者@Inject注解的构造方法获得。
3.建立普通类,我们需要注入的类。在构造函数上方通过@Inject注解标记。
public class MainPresenter { private Context context; @Inject public MainPresenter(Context context){// this.context = context; } }
4.在Application里面的使用
public class MyApplication extends Application { private ApplicationComponent mApplicationComponent; @Inject MainPresenter mMainPresenter ;// @Override public void onCreate() { super.onCreate(); initComponent(); } private void initComponent() { mApplicationComponent = DaggerApplicationComponent.builder() .applicationMoudle(new ApplicationMoudle(this)) .apiMoudle(new ApiMoudle()) .build(); mApplicationComponent.inject(this);//这样,就会把所有@Inject标记的对象进行注入操作 } }
dagger2的调用步骤:
1.创建DaggerApplicationComponent对象,创建需要Component依赖的Module对象(在程序中手动new创建)。
2.调用inject()注入。
dagger2的工作方式:
可以看到@Inject MainPresenter mMainPresenter 一句话就实现了注入(创建对象)。
我们可以看到MainPresenter的构造函数有一个@Inject注解
@Inject
public MainPresenter(Context context){
this.context = context;
}
1.对于@Inject标记的MainPresenter对象,dagger2首先会去到MainPresenter去找构造函数。如果该构造函数恰好也被@Inject标记,那么就会调用这个方法会new出对象,但是这里的构造函数需要一个参数context,而ApplicationModule有一个提供context的方法,所以context由ApplicationModule可以得到提供。那么,创建对象,就顺利完成了。
如果该构造函数没有被@Inject标记,那么就直接去Module里面去寻找对应的提供MainPresenter的方法,从而实现实例化创建对象。
那么,其实我们根本不需要Module,一样可以实现注入,使用构造器注入即可。
使用构造器注入具有局限性:
1.不能给这个类中的多个构造器作@Inject注解。
2.第三方类,系统类,我们就无法在他构造方法前面加@inject。
相关文章推荐
- android开源库---Dagger2入门学习(简单使用)
- Android Dagger2简单入门
- 详细解读Android中的搜索框(一)—— 简单小例子
- 详细解读Android中的搜索框(一)—— 简单小例子
- android 入门学习笔记 手机震动的节奏---vibrate对象及周期运用 和ToggleButton
- Android LOG机制的实现的详细解读
- android布局之一:简单入门
- Android之Handler简单运用(控制进度条)
- 一个简单的Android入门程序
- android中的线程的简单运用
- Android 中的 OpenGL 简单入门 (下)
- Android 中的 OpenGL 简单入门(上)
- phonegap 开发入门 PhoneGap官方网站上有详细的入门示例教程,这里,我针对使用PhoneGap进行Android移动应用的开发对其官网的Get Started进行一些介绍、补充。 Ste
- 正则表达式 特殊字符应用分析[简单详细入门必看]
- Android简单入门
- android AIDL简单入门(客户端与服务端)
- Android入门之简单GPS定位实例
- Android GridView宫格视图(二) 简单运用--SimpleAdapter
- 详细解读Android应用线程问题
- Android 简单例子以及入门学习资料链接