Dagger2学习笔记(二)
2015-11-10 17:37
381 查看
接着上一篇笔记,记录一下@scope这个注解的用法。
代码来自Dagger2Scopes:
ActivityScope的定义方法:
Application级别的component:ApplicationComponent
Activity级别的component:AbstractActivityComponent、GameListActivityComponent、GameDetailsComponent
ApplicationComponent使用@Singleton 修饰,其他3个component是dependencies 于ApplicationComponent,并且使用@ActivityScope 修饰。
一般使用流程是:
ApplicationComponent在应用的Application里build,这样整个应用生命周期内只有一个ApplicationComponent实例。
所有其他的component都依赖ApplicationComponent,若其他的component中需要可以由ApplicationComponent提供的对象,这些实例由ApplicationComponent负责提供。在这个例子里,加入在GameListActivityComponent 里生成某个对象实例需要传入InteractorExecutor类型参数,则这个参数由 ApplicationComponent负责提供,因为后者有能力提供而且前者依赖于后者。
还是以GameListActivityComponent 为例,这个对象中所有来自ApplicationComponent的实例的scope仍然是和在ApplicationComponent中相同,如果在ApplicationComponent中时singleton的,那依旧是singleton,而由GameListModule本身产生的实例则是本地的(“local singletons”),和GameListActivityComponent 的生命周期相同,所以如果创建另外一个GameListActivityComponent 实例,那么由GameListActivityComponent 本身产生的实例都将是新创建的。这里把英文解释贴出来:
下面解释一下为什么定义添加@ActivityScope可以起到管理生命周期的功能:
先看DaggerGameListActivityComponent的生成代码:
可以看到,前者是调用了ScopedProvider.create方法生成的,下面看一下ScopedProvider:
可以看到静态方法create只是生成了一个新的实例,关键在于get方法,因为所有获得实例的方法是这样调用的:
都是调用get获取的,下面是关键地方:
使用ScopedProvider的get时,会检测这个实例是否存在,如果是,则直接返回这个实例,否则就调用factory中get方法取得,并保存;
而普通的方式是直接调用factory的get方法取得实例;
最后看一下factory的get方法实现:
可以看到,get方法中时调用module中的provide方法生成实例的,这个就是我们前面定义的@Module中的@Provides方法,每次调用get都会生成一个新的实例
@ActivityScope的秘密就在于此,它只是声明了这个方法生成的实例被ScopedProvider实例持有(是它的一个field),而ScopedProvider实例又被DaggerXXXComponent持有,这样就保证了在component的生命周期内只生成一次这个实例。
学习资料:
Dependency injection with Dagger 2 - Custom scopes
代码来自Dagger2Scopes:
ActivityScope的定义方法:
@Scope @Retention(RetentionPolicy.RUNTIME) public @interface ActivityScope { }
Application级别的component:ApplicationComponent
@Singleton @Component(modules = ApplicationModule.class) public interface ApplicationComponent { //field injections for the dependencies of the Dagger2ScopesApp void inject(Dagger2ScopesApp app); //Exported to child components Application application(); InteractorExecutor threadExecutor(); MainThread mainThread(); }
Activity级别的component:AbstractActivityComponent、GameListActivityComponent、GameDetailsComponent
//AbstractActivityComponent @ActivityScope @Component(dependencies = ApplicationComponent.class, modules = ActivityModule.class) public interface AbstractActivityComponent { // Expose the activity to sub-graphs. Activity activityContext(); Navigator navigator(); ToolbarAnimator getToolbarAnimator(); }
//GameListActivityComponent @ActivityScope @Component(dependencies = ApplicationComponent.class, modules = { ActivityModule.class, GameListModule.class }) public interface GameListActivityComponent extends AbstractActivityComponent { //Main activity and game list fragments can get injected through this component. void inject(MainActivity mainActivity); void inject(LucasGameListFragment lucasGameListFragment); GameListPresenter gamePresenter(); LoadGames loadGames(); GameRepository gameRepository(); GameDataSource provideDataSource(); }
@ActivityScope @Component(dependencies = ApplicationComponent.class, modules = { ActivityModule.class, GameDetailsModule.class }) public interface GameDetailsComponent extends AbstractActivityComponent { void inject(GameDetailsActivity detailsActivity); void inject(GameDetailsFragment detailsFragment); GameDetailsPresenter getPresenter(); ChangeBookmarkGameStatus getBookmarkInteractor(); }
ApplicationComponent使用@Singleton 修饰,其他3个component是dependencies 于ApplicationComponent,并且使用@ActivityScope 修饰。
一般使用流程是:
ApplicationComponent在应用的Application里build,这样整个应用生命周期内只有一个ApplicationComponent实例。
所有其他的component都依赖ApplicationComponent,若其他的component中需要可以由ApplicationComponent提供的对象,这些实例由ApplicationComponent负责提供。在这个例子里,加入在GameListActivityComponent 里生成某个对象实例需要传入InteractorExecutor类型参数,则这个参数由 ApplicationComponent负责提供,因为后者有能力提供而且前者依赖于后者。
还是以GameListActivityComponent 为例,这个对象中所有来自ApplicationComponent的实例的scope仍然是和在ApplicationComponent中相同,如果在ApplicationComponent中时singleton的,那依旧是singleton,而由GameListModule本身产生的实例则是本地的(“local singletons”),和GameListActivityComponent 的生命周期相同,所以如果创建另外一个GameListActivityComponent 实例,那么由GameListActivityComponent 本身产生的实例都将是新创建的。这里把英文解释贴出来:
All instances taken from GameListActivityComponent inherited from ApplicationComponent still are singletons (in Application scope). But those which are produced by GameListModule (which is a part of GameListActivityComponent ) will be “local singletons” which live as long as this GameListActivityComponent instance. So every time we create another GameListActivityComponent instance by calling: GameListActivityComponent component = DaggerGameListActivityComponent.create(); objects taken from GameListModule are different instances.
下面解释一下为什么定义添加@ActivityScope可以起到管理生命周期的功能:
先看DaggerGameListActivityComponent的生成代码:
// 在initialize方法中:如果module中某个方法被修饰为@ActivityScope // 则它的初始化方法是这样的 this.provideViewProvider = ScopedProvider.create(MainModule_ProvideViewFactory.create(builder.mainModule)); // 而普通的,没有scope或者singleton修饰的,则是这样的 this.provideLoginInteractorProvider = InteractorsModule_ProvideLoginInteractorFactory.create(builder.interactorsModule);
可以看到,前者是调用了ScopedProvider.create方法生成的,下面看一下ScopedProvider:
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); } }
可以看到静态方法create只是生成了一个新的实例,关键在于get方法,因为所有获得实例的方法是这样调用的:
@Override public MainPresenter getLoginPresenter() { return providePresenterProvider.get(); }
都是调用get获取的,下面是关键地方:
使用ScopedProvider的get时,会检测这个实例是否存在,如果是,则直接返回这个实例,否则就调用factory中get方法取得,并保存;
而普通的方式是直接调用factory的get方法取得实例;
最后看一下factory的get方法实现:
@Override public LoginInteractor get() { LoginInteractor provided = module.provideLoginInteractor(); if (provided == null) { throw new NullPointerException("Cannot return null from a non-@Nullable @Provides method"); } return provided; }
可以看到,get方法中时调用module中的provide方法生成实例的,这个就是我们前面定义的@Module中的@Provides方法,每次调用get都会生成一个新的实例
@ActivityScope的秘密就在于此,它只是声明了这个方法生成的实例被ScopedProvider实例持有(是它的一个field),而ScopedProvider实例又被DaggerXXXComponent持有,这样就保证了在component的生命周期内只生成一次这个实例。
学习资料:
Dependency injection with Dagger 2 - Custom scopes
相关文章推荐
- Dagger2使用记录
- Android中使用Dagger2
- Android Dagger2(二)源码分析-对象是如何被注入的
- Android Dagger2(一) Dagger使用详解
- 红旅动漫App
- Dagger2
- Dagger2从0基础使用,到单例注入的正确姿势
- 依赖注入利器 - Dagger ‡
- Dagger2全面解析
- dagger2入门
- dagger2框架的学习理解
- android studio Dagger2的使用(环境搭建和helloword)
- MVP+Dagger2+Rxjava+Retrofit+GreenDao 开发的小应用,包含新闻、图片、视频3个大模块,代码封装良好
- 文章标题
- 从零开始学dagger2
- Dagger2进阶使用
- Dagger2的基本使用
- Android MVP+Dagger2使用教程
- 带你解析Dagger2
- Android神匕首—Dagger2依赖注入框架详解