前言
本文叙述:
- 数据结构和算法,23种规划形式,
- OKhttp,Retrofit,
- Glide,
- Dagger2,
- MVP,MVC,MVVM,MVI,
- Jetpack Room,
可能字数限制会分为2-3篇叙述
今天星期一,星期一,星期一
重视大众号:Android苦做舟
解锁 《Android十大板块文档》,让学习更靠近未来实战。已构成PDF版
内容如下:
1.2022最新Android11位大厂面试专题,128道附答案
2.音视频大合集,从初中高到面试包罗万象
3.Android车载运用大合集,从零开端一同学
4.功能优化大合集,离别优化烦恼
5.Framework大合集,从里到外剖析的明理解白
6.Flutter大合集,进阶Flutter高级工程师
7.compose大合集,拥抱新技术
8.Jetpack大合集,全家桶一次吃个够
9.架构大合集,轻松应对作业需求
10.Android根底篇大合集,根基安定楼房平地起
收拾不易,重视一下吧。开端进入正题,ღ( ・ᴗ・` )
三丶图片加载
1.Glide
1.1.根本运用流程
Glide最根本的运用流程便是下面这行代码,其它一切扩展的额外功用都是以其制作者链式调用的根底上增加的。
GlideApp.with(context).load(url).into(iv);
其间的GlideApp是注解处理器自动生成的,要运用GlideApp,必须先装备运用的AppGlideModule模块,里边能够为空装备,也能够依据实践状况增加指定装备。
@GlideModule
public class MyAppGlideModule extends AppGlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
// 实践运用中依据状况能够增加如下装备
<!--builder.setDefaultRequestOptions(new RequestOptions().format(DecodeFormat.PREFER_RGB_565));-->
<!--int memoryCacheSizeBytes = 1024 * 1024 * 20;-->
<!--builder.setMemoryCache(new LruResourceCache(memoryCacheSizeBytes));-->
<!--int bitmapPoolSizeBytes = 1024 * 1024 * 30;-->
<!--builder.setBitmapPool(new LruBitmapPool(bitmapPoolSizeBytes));-->
<!--int diskCacheSizeBytes = 1024 * 1024 * 100;-->
<!--builder.setDiskCache(new InternalCacheDiskCacheFactory(context, diskCacheSizeBytes));-->
}
}
接下来,本文将针对Glide的最新源码版本V4.8.0对Glide加载网络图片的流程进行详细地剖析与讲解,力争做到让读者朋友们知其然也知其所以然。
1.2.GlideApp.with(context)源码详解
首要,用这份Glide结构图让咱们对Glide的整体结构有一个初步的了解。
从GlideApp.with这行代码开端,内部主线履行流程如下。
GlideApp#with
return (GlideRequests) Glide.with(context);
Glide#with
return getRetriever(context).get(context);
return Glide.get(context).getRequestManagerRetriever();
// 外部运用了双重检锁的同步办法保证同一时刻只执一次Glide的初始化
checkAndInitializeGlide(context);
initializeGlide(context);
// 终究履行到Glide的另一个重载办法
initializeGlide(context, new GlideBuilder());
@SuppressWarnings("deprecation")
private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
Context applicationContext = context.getApplicationContext();
// 1、获取前面运用中带注解的GlideModule
GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
// 2、假如GlideModule为空或许可装备manifest里边的标志为true,则获取manifest里边
// 装备的GlideModule模块(manifestModules)。
List<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList();
if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled( )) {
manifestModules = new ManifestParser(applicationContext).parse();
}
...
RequestManagerRetriever.RequestManagerFactory factory =
annotationGeneratedModule != null
? annotationGeneratedModule.getRequestManag erFactory() : null;
builder.setRequestManagerFactory(factory);
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
module.applyOptions(applicationContext, builder);
}
if (annotationGeneratedModule != null) {
annotationGeneratedModule.applyOptions(applicatio nContext, builder);
}
// 3、初始化各种装备信息
Glide glide = builder.build(applicationContext);
// 4、把manifestModules以及annotationGeneratedModule里边的装备信息放到builder
// 里边(applyOptions)替换glide默认组件(registerComponents)
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
module.registerComponents(applicationContext, glide, glide.registry);
}
if (annotationGeneratedModule != null) {
annotationGeneratedModule.registerComponents(appl icationContext, glide, glide.registry);
}
applicationContext.registerComponentCallbacks(glide );
Glide.glide = glide;
}
GlideBuilder#build
@NonNull
Glide build(@NonNull Context context) {
// 创立恳求图片线程池sourceExecutor
if (sourceExecutor == null) {
sourceExecutor = GlideExecutor.newSourceExecutor();
}
// 创立硬盘缓存线程池diskCacheExecutor
if (diskCacheExecutor == null) {
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
}
// 创立动画线程池animationExecutor
if (animationExecutor == null) {
animationExecutor = GlideExecutor.newAnimationExecutor();
}
if (memorySizeCalculator == null) {
memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
}
if (connectivityMonitorFactory == null) {
connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
}
if (bitmapPool == null) {
// 依据设备的屏幕密度和尺寸设置各种pool的size
int size = memorySizeCalculator.getBitmapPoolSize();
if (size > 0) {
// 创立图片线程池LruBitmapPool,缓存一切被开释的bitmap
// 缓存战略在API大于19时,为SizeConfigStrategy,小于为AttributeStrategy。
// 其间SizeConfigStrategy是以bitmap的size和config为key,value为bitmap的HashMap
bitmapPool = new LruBitmapPool(size);
} else {
bitmapPool = new BitmapPoolAdapter();
}
}
// 创立方针数组缓存池LruArrayPool,默认4M
if (arrayPool == null) {
arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSiz eInBytes());
}
// 创立LruResourceCache,内存缓存
if (memoryCache == null) {
memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCa cheSize());
}
if (diskCacheFactory == null) {
diskCacheFactory = new InternalCacheDiskCacheFactory(context);
}
// 创立使命和资源办理引擎(线程池,内存缓存和硬盘缓存方针)
if (engine == null) {
engine =
new Engine(
memoryCache,
diskCacheFactory,
diskCacheExecutor,
sourceExecutor,
GlideExecutor.newUnlimitedSourceExecutor( ),
GlideExecutor.newAnimationExecutor(),
isActiveResourceRetentionAllowed);
}
RequestManagerRetriever requestManagerRetriever =
new RequestManagerRetriever(requestManagerFactory);
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptions.lock(),
defaultTransitionOptions);
}
Glide#Glide结构办法
Glide(...) {
...
// 注册办理使命履行方针的类(Registry)
// Registry是一个工厂,而其间一切注册的方针都是一个工厂职工,当使命分发时,
// 依据当时使命的性质,分发给相应职工进行处理
registry = new Registry();
...
// 这儿大概有60余次的append或register职工组件(解析器、编解码器、工厂类、转码类等等组件)
registry
.append(ByteBuffer.class, new ByteBufferEncoder())
.append(InputStream.class, new StreamEncoder(arrayPool))
// 依据给定子类产出对应类型的target(BitmapImageViewTarget / DrawableImageViewTarget)
ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();
glideContext =
new GlideContext(
context,
arrayPool,
registry,
imageViewTargetFactory,
defaultRequestOptions,
defaultTransitionOptions,
engine,
logLevel);
}
RequestManagerRetriever#get
@NonNull
public RequestManager get(@NonNull Context context) {
if (context == null) {
throw new IllegalArgumentException("You cannot start a load on a null Context");
} else if (Util.isOnMainThread() && !(context instanceof Application)) {
// 假如当时线程是主线程且context不是Application走相应的get重载办法
if (context instanceof FragmentActivity) {
return get((FragmentActivity) context);
} else if (context instanceof Activity) {
return get((Activity) context);
} else if (context instanceof ContextWrapper) {
return get(((ContextWrapper) context).getBaseContext());
}
}
// 不然直接将恳求与ApplicationLifecycle相关
return getApplicationManager(context);
}
这儿总结一下,关于当时传入的context是application或当时线程是子线程时,恳求的生命周期和ApplicationLifecycle相关,不然,context是FragmentActivity或Fragment时,在当时组件增加一个SupportFragment(SupportRequestManagerFragment),context是Activity时,在当时组件增加一个Fragment(RequestManagerFragment)。
GlideApp#with小结
-
初始化林林总总的装备信息(包含缓存,恳求线程池,巨细,图片格式等等)以及glide方针。
-
将glide恳求和application/SupportFragment/Fragment的生命周期绑定在一块。
with办法的履行流程
1.3.load(url)源码详解
GlideRequest(RequestManager)#load
return (GlideRequest<Drawable>) super.load(string);
return asDrawable().load(string);
// 1、asDrawable部分
return (GlideRequest<Drawable>) super.asDrawable();
return as(Drawable.class);
// 终究回来了一个GlideRequest(RequestManager的子类)
return new GlideRequest<>(glide, this, resourceClass, context);
// 2、load部分
return (GlideRequest<TranscodeType>) super.load(string);
return loadGeneric(string);
@NonNull
private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
// model则为设置的url
this.model = model;
// 记载url已设置
isModelSet = true;
return this;
}
能够看到,load这部分的源码很简单,便是给GlideRequest(RequestManager)设置了要恳求的mode(url),并记载了url已设置的状况。
load办法的履行流程
1.4.into(iv)源码详解
真实杂乱的当地要开端了。
RequestBuilder.into
@NonNull
public ViewTarget<ImageView, TranscodeType> into(@NonNull ImageView view) {
Util.assertMainThread();
Preconditions.checkNotNull(view);
RequestOptions requestOptions = this.requestOptions;
if (!requestOptions.isTransformationSet()
&& requestOptions.isTransformationAllowed()
&& view.getScaleType() != null) {
// Clone in this method so that if we use this RequestBuilder to load into a View and then
// into a different target, we don't retain the transformation applied based on the previous
// View's scale type.
switch (view.getScaleType()) {
// 这个RequestOptions里保存了要设置的scaleType,Glide本身封装了CenterCrop、CenterInside、
// FitCenter、CenterInside四种规格。
case CENTER_CROP:
requestOptions = requestOptions.clone().optionalCenterCrop();
break;
case CENTER_INSIDE:
requestOptions = requestOptions.clone().optionalCenterInside() ;
break;
case FIT_CENTER:
case FIT_START:
case FIT_END:
requestOptions = requestOptions.clone().optionalFitCenter();
break;
case FIT_XY:
requestOptions = requestOptions.clone().optionalCenterInside() ;
break;
case CENTER:
case MATRIX:
default:
// Do nothing.
}
}
// 留意,这个transcodeClass是指的drawable或bitmap
return into(
glideContext.buildImageViewTarget(view, transcodeClass),
/*targetListener=*/ null,
requestOptions);
}
GlideContext#buildImageViewTarget
return imageViewTargetFactory.buildTarget(imageView, transcodeClass);
ImageViewTargetFactory#buildTarget
@NonNull
@SuppressWarnings("unchecked")
public <Z> ViewTarget<ImageView, Z> buildTarget(@NonNull ImageView view,
@NonNull Class<Z> clazz) {
// 回来展示Bimtap/Drawable资源的方针方针
if (Bitmap.class.equals(clazz)) {
return (ViewTarget<ImageView, Z>) new BitmapImageViewTarget(view);
} else if (Drawable.class.isAssignableFrom(clazz)) {
return (ViewTarget<ImageView, Z>) new DrawableImageViewTarget(view);
} else {
throw new IllegalArgumentException(
"Unhandled class: " + clazz + ", try .as*(Class).transcode(ResourceTranscoder)");
}
}
能够看到,Glide内部只保护了两种target,一种是BitmapImageViewTarget,另一种则是DrawableImageViewTarget,接下来持续深化。
RequestBuilder#into
private <Y extends Target<TranscodeType>> Y into(
@NonNull Y target,
@Nullable RequestListener<TranscodeType> targetListener,
@NonNull RequestOptions options) {
Util.assertMainThread();
Preconditions.checkNotNull(target);
if (!isModelSet) {
throw new IllegalArgumentException("You must call #load() before calling #into()");
}
options = options.autoClone();
// 剖析1.树立恳求
Request request = buildRequest(target, targetListener, options);
Request previous = target.getRequest();
if (request.isEquivalentTo(previous)
&& !isSkipMemoryCacheWithCompletePreviousReques t(options, previous)) {
request.recycle();
// If the request is completed, beginning again will ensure the result is re-delivered,
// triggering RequestListeners and Targets. If the request is failed, beginning again will
// restart the request, giving it another chance to complete. If the request is already
// running, we can let it continue running without interruption.
if (!Preconditions.checkNotNull(previous).isRunni ng()) {
// Use the previous request rather than the new one to allow for optimizations like skipping
// setting placeholders, tracking and un-tracking Targets, and obtaining View dimensions
// that are done in the individual Request.
previous.begin();
}
return target;
}
requestManager.clear(target);
target.setRequest(request);
// 剖析2.真实追寻恳求的当地
requestManager.track(target, request);
return target;
}
// 剖析1
private Request buildRequest(
Target<TranscodeType> target,
@Nullable RequestListener<TranscodeType> targetListener,
RequestOptions requestOptions) {
return buildRequestRecursive(
target,
targetListener,
/*parentCoordinator=*/ null,
transitionOptions,
requestOptions.getPriority(),
requestOptions.getOverrideWidth(),
requestOptions.getOverrideHeight(),
requestOptions);
}
// 剖析1
private Request buildRequestRecursive(
Target<TranscodeType> target,
@Nullable RequestListener<TranscodeType> targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
RequestOptions requestOptions) {
// Build the ErrorRequestCoordinator first if necessary so we can update parentCoordinator.
ErrorRequestCoordinator errorRequestCoordinator = null;
if (errorBuilder != null) {
// 创立errorRequestCoordinator(异常处理方针)
errorRequestCoordinator = new ErrorRequestCoordinator(parentCoordinator);
parentCoordinator = errorRequestCoordinator;
}
// 递归树立缩略图恳求
Request mainRequest =
buildThumbnailRequestRecursive(
target,
targetListener,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight,
requestOptions);
if (errorRequestCoordinator == null) {
return mainRequest;
}
...
Request errorRequest = errorBuilder.buildRequestRecursive(
target,
targetListener,
errorRequestCoordinator,
errorBuilder.transitionOptions,
errorBuilder.requestOptions.getPriority(),
errorOverrideWidth,
errorOverrideHeight,
errorBuilder.requestOptions);
errorRequestCoordinator.setRequests(mainRequest, errorRequest);
return errorRequestCoordinator;
}
// 剖析1
private Request buildThumbnailRequestRecursive(
Target<TranscodeType> target,
RequestListener<TranscodeType> targetListener,
@Nullable RequestCoordinator parentCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight,
RequestOptions requestOptions) {
if (thumbnailBuilder != null) {
// Recursive case: contains a potentially recursive thumbnail request builder.
...
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
// 获取一个正常恳求方针
Request fullRequest =
obtainRequest(
target,
targetListener,
requestOptions,
coordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight);
isThumbnailBuilt = true;
// Recursively generate thumbnail requests.
// 运用递归的办法树立一个缩略图恳求方针
Request thumbRequest =
thumbnailBuilder.buildRequestRecursive(
target,
targetListener,
coordinator,
thumbTransitionOptions,
thumbPriority,
thumbOverrideWidth,
thumbOverrideHeight,
thumbnailBuilder.requestOptions);
isThumbnailBuilt = false;
// coordinator(ThumbnailRequestCoordinator)是作为两者的和谐者,
// 能够一同加载缩略图和正常的图的恳求
coordinator.setRequests(fullRequest, thumbRequest);
return coordinator;
} else if (thumbSizeMultiplier != null) {
// Base case: thumbnail multiplier generates a thumbnail request, but cannot recurse.
// 当设置了缩略的份额thumbSizeMultiplier(0 ~ 1)时,
// 不需求递归树立缩略图恳求
ThumbnailRequestCoordinator coordinator = new ThumbnailRequestCoordinator(parentCoordinator);
Request fullRequest =
obtainRequest(
target,
targetListener,
requestOptions,
coordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight);
RequestOptions thumbnailOptions = requestOptions.clone()
.sizeMultiplier(thumbSizeMultiplier);
Request thumbnailRequest =
obtainRequest(
target,
targetListener,
thumbnailOptions,
coordinator,
transitionOptions,
getThumbnailPriority(priority),
overrideWidth,
overrideHeight);
coordinator.setRequests(fullRequest, thumbnailRequest);
return coordinator;
} else {
// Base case: no thumbnail.
// 没有缩略图恳求时,直接获取一个正常图恳求
return obtainRequest(
target,
targetListener,
requestOptions,
parentCoordinator,
transitionOptions,
priority,
overrideWidth,
overrideHeight);
}
}
private Request obtainRequest(
Target<TranscodeType> target,
RequestListener<TranscodeType> targetListener,
RequestOptions requestOptions,
RequestCoordinator requestCoordinator,
TransitionOptions<?, ? super TranscodeType> transitionOptions,
Priority priority,
int overrideWidth,
int overrideHeight) {
// 终究实践回来的是一个SingleRequest方针(将制定的资源加载进对应的Target
return SingleRequest.obtain(
context,
glideContext,
model,
transcodeClass,
requestOptions,
overrideWidth,
overrideHeight,
priority,
target,
targetListener,
requestListeners,
requestCoordinator,
glideContext.getEngine(),
transitionOptions.getTransitionFactory());
}
从上源码剖析可知,咱们在剖析1处的buildRequest()办法里树立了恳求,且最多可一同进行缩略图和正常图的恳求,终究,调用了requestManager.track(target, request)办法,接着看看track里边做了什么。
RequestManager#track
// 剖析2
void track(@NonNull Target<?> target, @NonNull Request request) {
// 参加一个target方针集合(Set)
targetTracker.track(target);
requestTracker.runRequest(request);
}
RequestTracker#runRequest
/**
* Starts tracking the given request.
*/
// 剖析2
public void runRequest(@NonNull Request request) {
requests.add(request);
if (!isPaused) {
// 假如不是暂停状况则开端恳求
request.begin();
} else {
request.clear();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Paused, delaying request");
}
// 不然清空恳求,参加延迟恳求行列(为了对这些恳求保持一个强引证,运用了ArrayList完成)
pendingRequests.add(request);
}
}
SingleRequest#begin
// 剖析2
@Override
public void begin() {
...
if (model == null) {
...
// model(url)为空,回调加载失利
onLoadFailed(new GlideException("Received null model"), logLevel);
return;
}
if (status == Status.RUNNING) {
throw new IllegalArgumentException("Cannot restart a running request");
}
if (status == Status.COMPLETE) {
onResourceReady(resource, DataSource.MEMORY_CACHE);
return;
}
status = Status.WAITING_FOR_SIZE;
if (Util.isValidDimensions(overrideWidth, overrideHeight)) {
// 当运用override() API为图片指定了一个固定的宽高时直接履行onSizeReady,
// 终究的中心处理坐落onSizeReady
onSizeReady(overrideWidth, overrideHeight);
} else {
// 依据imageView的宽高算出图片的宽高,终究也会走到onSizeReady
target.getSize(this);
}
if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)
&& canNotifyStatusChanged()) {
// 预先加载设置的缩略图
target.onLoadStarted(getPlaceholderDrawable());
}
if (IS_VERBOSE_LOGGABLE) {
logV("finished run method in " + LogTime.getElapsedMillis(startTime));
}
}
从requestManager.track(target, request)开端,终究会履行到SingleRequest#begin()办法的onSizeReady,能够猜到(由于后边只做了预加载缩略图的处理),真实的恳求便是从这儿开端的,咱们进去一探终究~
SingleRequest#onSizeReady
// 剖析2
@Override
public void onSizeReady(int width, int height) {
stateVerifier.throwIfRecycled();
...
status = Status.RUNNING;
float sizeMultiplier = requestOptions.getSizeMultiplier();
this.width = maybeApplySizeMultiplier(width, sizeMultiplier);
this.height = maybeApplySizeMultiplier(height, sizeMultiplier);
...
// 依据给定的装备进行加载,engine是一个担任加载、办理活跃和缓存资源的引擎类
loadStatus = engine.load(
glideContext,
model,
requestOptions.getSignature(),
this.width,
this.height,
requestOptions.getResourceClass(),
transcodeClass,
priority,
requestOptions.getDiskCacheStrategy(),
requestOptions.getTransformations(),
requestOptions.isTransformationRequired(),
requestOptions.isScaleOnlyOrNoTransform(),
requestOptions.getOptions(),
requestOptions.isMemoryCacheable(),
requestOptions.getUseUnlimitedSourceGeneratorsP ool(),
requestOptions.getUseAnimationPool(),
requestOptions.getOnlyRetrieveFromCache(),
this);
...
}
总算看到Engine类了,感觉间隔成功不远了,持续~
Engine#load
public <R> LoadStatus load(
GlideContext glideContext,
Object model,
Key signature,
int width,
int height,
Class<?> resourceClass,
Class<R> transcodeClass,
Priority priority,
DiskCacheStrategy diskCacheStrategy,
Map<Class<?>, Transformation<?>> transformations,
boolean isTransformationRequired,
boolean isScaleOnlyOrNoTransform,
Options options,
boolean isMemoryCacheable,
boolean useUnlimitedSourceExecutorPool,
boolean useAnimationPool,
boolean onlyRetrieveFromCache,
ResourceCallback cb) {
...
// 先从弱引证中查找,假如有的话回调onResourceReady并直接回来
EngineResource<?> active = loadFromActiveResources(key, isMemoryCacheable);
if (active != null) {
cb.onResourceReady(active, DataSource.MEMORY_CACHE);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Loaded resource from active resources", startTime, key);
}
return null;
}
// 没有再从内存中查找,有的话会取出并放到ActiveResources(内部保护的弱引证缓存map)里边
EngineResource<?> cached = loadFromCache(key, isMemoryCacheable);
if (cached != null) {
cb.onResourceReady(cached, DataSource.MEMORY_CACHE);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Loaded resource from cache", startTime, key);
}
return null;
}
EngineJob<?> current = jobs.get(key, onlyRetrieveFromCache);
if (current != null) {
current.addCallback(cb);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Added to existing load", startTime, key);
}
return new LoadStatus(cb, current);
}
// 假如内存中没有,则创立engineJob(decodejob的回调类,办理下载进程以及状况)
EngineJob<R> engineJob =
engineJobFactory.build(
key,
isMemoryCacheable,
useUnlimitedSourceExecutorPool,
useAnimationPool,
onlyRetrieveFromCache);
// 创立解析作业方针
DecodeJob<R> decodeJob =
decodeJobFactory.build(
glideContext,
model,
key,
signature,
width,
height,
resourceClass,
transcodeClass,
priority,
diskCacheStrategy,
transformations,
isTransformationRequired,
isScaleOnlyOrNoTransform,
onlyRetrieveFromCache,
options,
engineJob);
// 放在Jobs内部保护的HashMap中
jobs.put(key, engineJob);
// 重视点8 后边剖析会用到
// 注册ResourceCallback接口
engineJob.addCallback(cb);
// 内部敞开线程去恳求
engineJob.start(decodeJob);
if (VERBOSE_IS_LOGGABLE) {
logWithTimeAndKey("Started new load", startTime, key);
}
return new LoadStatus(cb, engineJob);
}
public void start(DecodeJob<R> decodeJob) {
this.decodeJob = decodeJob;
// willDecodeFromCache办法内部依据不同的阶段stage,假如是RESOURCE_CACHE/DATA_CACHE则回来true,运用diskCacheExecutor,不然调用getActiveSourceExecutor,内部会依据相应的条件回来sourceUnlimitedExecutor/animationExecutor/sourceExecutor
GlideExecutor executor =
decodeJob.willDecodeFromCache()
? diskCacheExecutor
: getActiveSourceExecutor();
executor.execute(decodeJob);
}
能够看到,终究Engine(引擎)类内部会履行到本身的start办法,它会依据不同的装备选用不同的线程池运用diskCacheExecutor/sourceUnlimitedExecutor/animationExecutor/sourceExecutor来履行终究的解码使命decodeJob。
DecodeJob#run
runWrapped();
private void runWrapped() {
switch (runReason) {
case INITIALIZE:
stage = getNextStage(Stage.INITIALIZE);
// 重视点1
currentGenerator = getNextGenerator();
// 重视点2 内部会调用相应Generator的startNext()
runGenerators();
break;
case SWITCH_TO_SOURCE_SERVICE:
runGenerators();
break;
case DECODE_DATA:
// 重视点3 将获取的数据解码成对应的资源
decodeFromRetrievedData();
break;
default:
throw new IllegalStateException("Unrecognized run reason: " + runReason);
}
}
// 重视点1,完好状况下,会异步依次生成这儿的ResourceCacheGenerator、DataCacheGenerator和SourceGenerator方针,并在之后履行其间的startNext()
private DataFetcherGenerator getNextGenerator() {
switch (stage) {
case RESOURCE_CACHE:
return new ResourceCacheGenerator(decodeHelper, this);
case DATA_CACHE:
return new DataCacheGenerator(decodeHelper, this);
case SOURCE:
return new SourceGenerator(decodeHelper, this);
case FINISHED:
return null;
default:
throw new IllegalStateException("Unrecognized stage: " + stage);
}
}
SourceGenerator#startNext
// 重视点2
@Override
public boolean startNext() {
// dataToCache数据不为空的话缓存到硬盘(榜首履行该办法是不会调用的)
if (dataToCache != null) {
Object data = dataToCache;
dataToCache = null;
cacheData(data);
}
if (sourceCacheGenerator != null && sourceCacheGenerator.startNext()) {
return true;
}
sourceCacheGenerator = null;
loadData = null;
boolean started = false;
while (!started && hasNextModelLoader()) {
// 重视点4 getLoadData()办法内部会在modelLoaders里边找到ModelLoder方针
// (每个Generator对应一个ModelLoader),
// 并运用modelLoader.buildLoadData办法回来一个loadData列表
loadData = helper.getLoadData().get(loadDataListIndex++);
if (loadData != null
&& (helper.getDiskCacheStrategy().isDataCache able(loadData.fetcher.getDataSource())
|| helper.hasLoadPath(loadData.fetcher.getDat aClass()))) {
started = true;
// 重视点6 经过loadData方针的fetcher方针(有重视点3的剖析可知其完成类为HttpUrlFetcher)的
// loadData办法来获取图片数据
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
DecodeHelper#getLoadData
List<LoadData<?>> getLoadData() {
if (!isLoadDataSet) {
isLoadDataSet = true;
loadData.clear();
List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model) ;
//noinspection ForLoopReplaceableByForEach to improve perf
for (int i = 0, size = modelLoaders.size(); i < size; i++) {
ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
// 留意:这儿终究是经过HttpGlideUrlLoader的buildLoadData获取到实践的loadData方针
LoadData<?> current =
modelLoader.buildLoadData(model, width, height, options);
if (current != null) {
loadData.add(current);
}
}
}
return loadData;
}
HttpGlideUrlLoader#buildLoadData
@Override
public LoadData<InputStream> buildLoadData(@NonNull GlideUrl model, int width, int height,
@NonNull Options options) {
// GlideUrls memoize parsed URLs so caching them saves a few object instantiations and time
// spent parsing urls.
GlideUrl url = model;
if (modelCache != null) {
url = modelCache.get(model, 0, 0);
if (url == null) {
// 重视点5
modelCache.put(model, 0, 0, model);
url = model;
}
}
int timeout = options.get(TIMEOUT);
// 留意,这儿创立了一个DataFetcher的完成类HttpUrlFetcher
return new LoadData<>(url, new HttpUrlFetcher(url, timeout));
}
// 重视点5
public void put(A model, int width, int height, B value) {
ModelKey<A> key = ModelKey.get(model, width, height);
// 终究是经过LruCache来缓存对应的值,key是一个ModelKey方针(由model、width、height三个特点组成)
cache.put(key, value);
}
从这儿的剖析,咱们理解了HttpUrlFetcher实践上便是终究的恳求履行者,并且,咱们知道了Glide会运用LruCache来对解析后的url来进行缓存,以便后续能够省去解析url的时间。
HttpUrlFetcher#loadData
@Override
public void loadData(@NonNull Priority priority,
@NonNull DataCallback<? super InputStream> callback) {
long startTime = LogTime.getLogTime();
try {
// 重视点6
// loadDataWithRedirects内部是经过HttpURLConnection网络恳求数据
InputStream result = loadDataWithRedirects(glideUrl.toURL(), 0, null, glideUrl.getHeaders());
// 恳求成功回调onDataReady()
callback.onDataReady(result);
} catch (IOException e) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Failed to load data for url", e);
}
callback.onLoadFailed(e);
} finally {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Finished http url fetcher fetch in " + LogTime.getElapsedMillis(startTime));
}
}
}
private InputStream loadDataWithRedirects(URL url, int redirects, URL lastUrl,
Map<String, String> headers) throws IOException {
...
urlConnection.connect();
// Set the stream so that it's closed in cleanup to avoid resource leaks. See #2352.
stream = urlConnection.getInputStream();
if (isCancelled) {
return null;
}
final int statusCode = urlConnection.getResponseCode();
// 只要是2xx办法的状况码则判别为成功
if (isHttpOk(statusCode)) {
// 从urlConnection中获取资源流
return getStreamForSuccessfulRequest(urlConnection);
} else if (isHttpRedirect(statusCode)) {
...
// 重定向恳求
return loadDataWithRedirects(redirectUrl, redirects + 1, url, headers);
} else if (statusCode == INVALID_STATUS_CODE) {
throw new HttpException(statusCode);
} else {
throw new HttpException(urlConnection.getResponseMessage(), statusCode);
}
}
private InputStream getStreamForSuccessfulRequest(HttpURLConnection urlConnection)
throws IOException {
if (TextUtils.isEmpty(urlConnection.getContentEncoding())) {
int contentLength = urlConnection.getContentLength();
stream = ContentLengthInputStream.obtain(urlConnection.getInputStr eam(), contentLength);
} else {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Got non empty content encoding: " + urlConnection.getContentEncoding());
}
stream = urlConnection.getInputStream();
}
return stream;
}
在HttpUrlFetcher#loadData办法的loadDataWithRedirects里边,Glide经过原生的HttpURLConnection进行恳求后,并调用getStreamForSuccessfulRequest()办法获取到了终究的图片流。
DecodeJob#run
在咱们经过HtttpUrlFetcher的loadData()办法恳求得到对应的流之后,咱们还必须对流进行处理得到终究咱们想要的资源。这儿咱们回到第10步DecodeJob#run办法的重视点3处,这行代码将会对流进行解码。
decodeFromRetrievedData();
接下来,持续看看他内部的处理。
private void decodeFromRetrievedData() {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Retrieved data", startFetchTime,
"data: " + currentData
+ ", cache key: " + currentSourceKey
+ ", fetcher: " + currentFetcher);
}
Resource<R> resource = null;
try {
// 中心代码
// 从数据中解码得到资源
resource = decodeFromData(currentFetcher, currentData, currentDataSource);
} catch (GlideException e) {
e.setLoggingDetails(currentAttemptingKey, currentDataSource);
throwables.add(e);
}
if (resource != null) {
// 重视点8
// 编码和发布终究得到的Resource<Bitmap>方针
notifyEncodeAndRelease(resource, currentDataSource);
} else {
runGenerators();
}
}
private <Data> Resource<R> decodeFromData(DataFetcher<?> fetcher, Data data,
DataSource dataSource) throws GlideException {
try {
if (data == null) {
return null;
}
long startTime = LogTime.getLogTime();
// 中心代码
// 进一步包装了解码办法
Resource<R> result = decodeFromFetcher(data, dataSource);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
logWithTimeAndKey("Decoded result " + result, startTime);
}
return result;
} finally {
fetcher.cleanup();
}
}
@SuppressWarnings("unchecked")
private <Data> Resource<R> decodeFromFetcher(Data data, DataSource dataSource)
throws GlideException {
LoadPath<Data, ?, R> path = decodeHelper.getLoadPath((Class<Data>) data.getClass());
// 中心代码
// 将解码使命分发给LoadPath
return runLoadPath(data, dataSource, path);
}
private <Data, ResourceType> Resource<R> runLoadPath(Data data, DataSource dataSource,
LoadPath<Data, ResourceType, R> path) throws GlideException {
Options options = getOptionsWithHardwareConfig(dataSource);
// 将数据进一步包装
DataRewinder<Data> rewinder = glideContext.getRegistry().getRewinder(data);
try {
// ResourceType in DecodeCallback below is required for compilation to work with gradle.
// 中心代码
// 将解码使命分发给LoadPath
return path.load(
rewinder, options, width, height, new DecodeCallback<ResourceType>(dataSource));
} finally {
rewinder.cleanup();
}
}
LoadPath#load
public Resource<Transcode> load(DataRewinder<Data> rewinder, @NonNull Options options, int width,
int height, DecodePath.DecodeCallback<ResourceType> decodeCallback) throws GlideException {
List<Throwable> throwables = Preconditions.checkNotNull(listPool.acquire());
try {
// 中心代码
return loadWithExceptionList(rewinder, options, width, height, decodeCallback, throwables);
} finally {
listPool.release(throwables);
}
}
private Resource<Transcode> loadWithExceptionList(DataRewinder<Data> rewinder,
@NonNull Options options,
int width, int height, DecodePath.DecodeCallback<ResourceType> decodeCallback,
List<Throwable> exceptions) throws GlideException {
Resource<Transcode> result = null;
//noinspection ForLoopReplaceableByForEach to improve perf
for (int i = 0, size = decodePaths.size(); i < size; i++) {
DecodePath<Data, ResourceType, Transcode> path = decodePaths.get(i);
try {
// 中心代码
// 将解码使命又进一步分发给DecodePath的decode办法去解码
result = path.decode(rewinder, width, height, options, decodeCallback);
} catch (GlideException e) {
exceptions.add(e);
}
if (result != null) {
break;
}
}
if (result == null) {
throw new GlideException(failureMessage, new ArrayList<>(exceptions));
}
return result;
}
DecodePath#decode
public Resource<Transcode> decode(DataRewinder<DataType> rewinder, int width, int height,
@NonNull Options options, DecodeCallback<ResourceType> callback) throws GlideException {
// 中心代码
// 持续调用DecodePath的decodeResource办法去解分出数据
Resource<ResourceType> decoded = decodeResource(rewinder, width, height, options);
Resource<ResourceType> transformed = callback.onResourceDecoded(decoded);
return transcoder.transcode(transformed, options);
}
@NonNull
private Resource<ResourceType> decodeResource(DataRewinder<DataType> rewinder, int width,
int height, @NonNull Options options) throws GlideException {
List<Throwable> exceptions = Preconditions.checkNotNull(listPool.acquire());
try {
// 中心代码
return decodeResourceWithList(rewinder, width, height, options, exceptions);
} finally {
listPool.release(exceptions);
}
}
@NonNull
private Resource<ResourceType> decodeResourceWithList(DataRewinder<DataType> rewinder, int width,
int height, @NonNull Options options, List<Throwable> exceptions) throws GlideException {
Resource<ResourceType> result = null;
//noinspection ForLoopReplaceableByForEach to improve perf
for (int i = 0, size = decoders.size(); i < size; i++) {
ResourceDecoder<DataType, ResourceType> decoder = decoders.get(i);
try {
DataType data = rewinder.rewindAndGet();
if (decoder.handles(data, options)) {
// 获取包装的数据
data = rewinder.rewindAndGet();
// 中心代码
// 依据DataType和ResourceType的类型分发给不同的解码器Decoder
result = decoder.decode(data, width, height, options);
}
} catch (IOException | RuntimeException | OutOfMemoryError e) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Failed to decode data for " + decoder, e);
}
exceptions.add(e);
}
if (result != null) {
break;
}
}
if (result == null) {
throw new GlideException(failureMessage, new ArrayList<>(exceptions));
}
return result;
}
能够看到,经过一连串的嵌套调用,终究履行到了decoder.decode()这行代码,decode是一个ResourceDecoder<DataType, ResourceType>接口(资源解码器),依据不同的DataType和ResourceType它会有不同的完成类,这儿的完成类是ByteBufferBitmapDecoder,接下来让咱们来看看这个解码器内部的解码流程。
ByteBufferBitmapDecoder#decode
/**
* Decodes {@link android.graphics.Bitmap Bitmaps} from {@link java.nio.ByteBuffer ByteBuffers}.
*/
public class ByteBufferBitmapDecoder implements ResourceDecoder<ByteBuffer, Bitmap> {
...
@Override
public Resource<Bitmap> decode(@NonNull ByteBuffer source, int width, int height,
@NonNull Options options)
throws IOException {
InputStream is = ByteBufferUtil.toStream(source);
// 中心代码
return downsampler.decode(is, width, height, options);
}
}
能够看到,终究是运用了一个downsampler,它是一个紧缩器,主要是对流进行解码,紧缩,圆角等处理。
DownSampler#decode
public Resource<Bitmap> decode(InputStream is, int outWidth, int outHeight,
Options options) throws IOException {
return decode(is, outWidth, outHeight, options, EMPTY_CALLBACKS);
}
@SuppressWarnings({"resource", "deprecation"})
public Resource<Bitmap> decode(InputStream is, int requestedWidth, int requestedHeight,
Options options, DecodeCallbacks callbacks) throws IOException {
Preconditions.checkArgument(is.markSupported(), "You must provide an InputStream that supports"
+ " mark()");
...
try {
// 中心代码
Bitmap result = decodeFromWrappedStreams(is, bitmapFactoryOptions,
downsampleStrategy, decodeFormat, isHardwareConfigAllowed, requestedWidth,
requestedHeight, fixBitmapToRequestedDimensions, callbacks);
// 重视点7
// 解码得到Bitmap方针后,包装成BitmapResource方针回来,
// 经过内部的get办法得到Resource<Bitmap>方针
return BitmapResource.obtain(result, bitmapPool);
} finally {
releaseOptions(bitmapFactoryOptions);
byteArrayPool.put(bytesForOptions);
}
}
private Bitmap decodeFromWrappedStreams(InputStream is,
BitmapFactory.Options options, DownsampleStrategy downsampleStrategy,
DecodeFormat decodeFormat, boolean isHardwareConfigAllowed, int requestedWidth,
int requestedHeight, boolean fixBitmapToRequestedDimensions,
DecodeCallbacks callbacks) throws IOException {
// 省去计算紧缩份额等一系列非中心逻辑
...
// 中心代码
Bitmap downsampled = decodeStream(is, options, callbacks, bitmapPool);
callbacks.onDecodeComplete(bitmapPool, downsampled);
...
// Bimtap旋转处理
...
return rotated;
}
private static Bitmap decodeStream(InputStream is, BitmapFactory.Options options,
DecodeCallbacks callbacks, BitmapPool bitmapPool) throws IOException {
...
TransformationUtils.getBitmapDrawableLock().lock();
try {
// 中心代码
result = BitmapFactory.decodeStream(is, null, options);
} catch (IllegalArgumentException e) {
...
} finally {
TransformationUtils.getBitmapDrawableLock().unlock();
}
if (options.inJustDecodeBounds) {
is.reset();
}
return result;
}
从以上源码流程咱们知道,终究是在DownSampler的decodeStream()办法中运用了BitmapFactory.decodeStream()来得到Bitmap方针。然后,咱们来剖析下图片时怎么显现的,咱们回到过程19的DownSampler#decode办法,看到重视点7,这儿是将Bitmap包装成BitmapResource方针回来,经过内部的get办法能够得到Resource方针,再回到过程15的DecodeJob#run办法,这是运用了notifyEncodeAndRelease()办法对Resource方针进行了发布。
DecodeJob#notifyEncodeAndRelease
private void notifyEncodeAndRelease(Resource<R> resource, DataSource dataSource) {
...
notifyComplete(result, dataSource);
...
}
private void notifyComplete(Resource<R> resource, DataSource dataSource) {
setNotifiedOrThrow();
callback.onResourceReady(resource, dataSource);
}
从以上EngineJob的源码可知,它完成了DecodeJob.CallBack这个接口。
class EngineJob<R> implements DecodeJob.Callback<R>,
Poolable {
...
}
EngineJob#onResourceReady
@Override
public void onResourceReady(Resource<R> resource, DataSource dataSource) {
this.resource = resource;
this.dataSource = dataSource;
MAIN_THREAD_HANDLER.obtainMessage(MSG_COMPLETE, this).sendToTarget();
}
private static class MainThreadCallback implements Handler.Callback{
...
@Override
public boolean handleMessage(Message message) {
EngineJob<?> job = (EngineJob<?>) message.obj;
switch (message.what) {
case MSG_COMPLETE:
// 中心代码
job.handleResultOnMainThread();
break;
...
}
return true;
}
}
从以上源码可知,经过主线程Handler方针进行切换线程,然后在主线程调用了handleResultOnMainThread这个办法。
@Synthetic
void handleResultOnMainThread() {
...
//noinspection ForLoopReplaceableByForEach to improve perf
for (int i = 0, size = cbs.size(); i < size; i++) {
ResourceCallback cb = cbs.get(i);
if (!isInIgnoredCallbacks(cb)) {
engineResource.acquire();
cb.onResourceReady(engineResource, dataSource);
}
}
...
}
这儿又经过一个循环调用了一切ResourceCallback的办法,让咱们回到过程9处Engine#load办法的重视点8这行代码,这儿对ResourceCallback进行了注册,在过程8出SingleRequest#onSizeReady办法里的engine.load中,咱们看到终究一个参数,传入的是this,能够理解,engineJob.addCallback(cb)这儿的cb的完成类便是SingleRequest。接下来,让咱们看看SingleRequest的onResourceReady办法。
SingleRequest#onResourceReady
/**
* A callback method that should never be invoked directly.
*/
@SuppressWarnings("unchecked")
@Override
public void onResourceReady(Resource<?> resource, DataSource dataSource) {
...
// 从Resource<Bitmap>中得到Bitmap方针
Object received = resource.get();
...
onResourceReady((Resource<R>) resource, (R) received, dataSource);
}
private void onResourceReady(Resource<R> resource, R resultDataSource dataSource) {
...
try {
...
if (!anyListenerHandledUpdatingTarget) {
Transition<? super R> animation =
animationFactory.build(dataSource, isFirstResource);
// 中心代码
target.onResourceReady(result, animation);
}
} finally {
isCallingCallbacks = false;
}
notifyLoadSuccess();
}
在SingleRequest#onResourceReady办法中又调用了target.onResourceReady(result, animation)办法,这儿的target其实便是咱们在into办法中树立的那个BitmapImageViewTarget,看到BitmapImageViewTarget类,咱们并没有发现onResourceReady办法,可是咱们从它的子类ImageViewTarget中发现了onResourceReady办法,从这儿持续往下看。
ImageViewTarget#onResourceReady
public abstract class ImageViewTarget<Z> extends ViewTarget<ImageView, Z>
implements Transition.ViewAdapter {
...
@Override
public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
if (transition == null || !transition.transition(resource, this)) {
// 中心代码
setResourceInternal(resource);
} else {
maybeUpdateAnimatable(resource);
}
}
...
private void setResourceInternal(@Nullable Z resource) {
// Order matters here. Set the resource first to make sure that the Drawable has a valid and
// non-null Callback before starting it.
// 中心代码
setResource(resource);
maybeUpdateAnimatable(resource);
}
// 中心代码
protected abstract void setResource(@Nullable Z resource);
}
这儿咱们在回到BitmapImageViewTarget的setResource办法中,总算看到Bitmap被设置到了当时的imageView上了。
public class BitmapImageViewTarget extends ImageViewTarget<Bitmap> {
...
@Override
protected void setResource(Bitmap resource) {
view.setImageBitmap(resource);
}
}
到这儿,咱们的剖析就完毕了,从以上的剖析可知,Glide将大部分的逻辑处理都放在了终究一个into办法中,里边经过了20多个剖析过程才将恳求图片流、解码出图片,到终究设置到对应的imageView上。
1.5.完好Glide加载流程图
能够看到,Glide最中心的逻辑都聚集在into()办法中,它里边的规划精巧而杂乱,这部分的源码剖析非常耗时,可是,假如你真真实正地去一步步去深化其间,你或许在Android进阶之路上将会有顿悟的感觉。
四丶Dagger 2
1.预备常识
1.1.@Inject
告知dagger这个字段或类需求依靠注入,然后在需求依靠的当地运用这个注解,dagger会自动生成这个结构器的实例。
获取所需依靠:
- 大局变量注入
- 办法注入
供给所需实例:
- 结构器注入(假如有多个结构函数,只能注解一个,不然编译报错)
1.2.@Module
类注解,表明此类的办法是供给依靠的,它告知dagger在哪能够找到依靠。用于不能用@Inject供给依靠的当地,如第三方库供给的类,根本数据类型等不能修改源码的状况。
留意:Dagger2会优先在@Module注解的类上查找依靠,没有的状况才会去查询类的@Inject结构办法
1.3.@Singleton
声明这是一个单例,在保证只要一个Component并且不再从头build()之后,方针只会被初始化一次,之后的每次都会被注入相同的方针,它便是一个内置的效果域。
关于@Singleton,咱们可能会产生一些误解,这儿详细论述下:
- Singleton简单给人构成一种误解便是用Singleton注解后在整个Java代码中都是单例,但实践上他和Scope一样,只是在同一个Component是单例。也便是说,假如从头调用了component的build()办法,即便运用了Singleton注解了,但仍然获取的是不同的方针。
- 它表明晰**@Singleton注解只是声明晰这是一个单例,为的只是进步代码可读性,其实真实控制方针生命周期的仍是Component**。同理,自界说的@ActivityScope 、@ApplicationScope也仅仅是一个声明的效果,真实控制方针生命周期的仍是Component。
1.4.@Providers
只在@Module中运用,用于供给结构好的实例。一般与@Singleton搭配,用单例办法的办法对外供给依靠,是一种代替@Inject注解结构办法的办法。
留意:
- 运用了@Providers的办法应运用provide作为前缀,运用了@Module的类应运用Module作为后缀。
- 假如@Providers办法或@Inject结构办法有参数,要保证它能够被dagger获取到,比方经过其它@Providers办法或许@Inject注解结构器的办法得到。
1.5.@Component
@Component作为Dagger2的容器总管,它拥有着@Inject与@Module的一切依靠。一同,它也是一枚注射器,用于获取所需依靠和供给所需依靠的桥梁。这儿的桥梁即指@Inject和@Module(或@Inject结构办法)之间的桥梁。界说时需求列出呼应的Module组成,此外,还能够运用dependencies承继父Component。
Component与Module的差异:
Component既是注射器也是一个容器总管,而module则是作为容器总管Component的子容器,实质是一个用于供给依靠的模块。
1.6.@Scope
注解效果域,经过自界说注解限制方针效果规模,增强可读性。
@Scope有两种常用的运用场景:
- 模仿Singleton代表大局单例,与Component生命周期相关。
- 模仿部分单例,如登录到退出登录期间。
1.7.@Qualifier
限制符,利用它界说注解类以用于区分类的不同实例。例如:2个办法回来不同的Person方针,比方说小明和小华,为了区分,运用@Qualifier界说的注解类。
dependencies
运用它表明ChildComponent依靠于FatherComponent,如下所示:
@Component(modules = ChildModule.class, dependencies = FatherComponent.class)
public interface ChildComponent {
...
}
1.8.@SubComponent
表明是一个子@Component,它能将运用的不同部分封装起来,用来代替@Dependencies。
2.简单示例
2.1.首要,创立一个BaseActivityComponent的Subcomponent:
@Subcomponent(modules = {AndroidInjectionModule.class})
public interface BaseActivityComponent extends AndroidInjector<BaseActivity> {
@Subcomponent.Builder
abstract class BaseBuilder extends AndroidInjector.Builder<BaseActivity>{
}
}
这儿必须要注解成@Subcomponent.Builder表明是顶级@Subcomponent的内部类。AndroidInjector.Builder的泛型指定了BaseActivity,即表明每一个承继于BaseActivity的Activity都承继于同一个子组件(BaseActivityComponent)。
2.2.然后,创立一个将会导入Subcomponent的公有Module。
// 1
@Module(subcomponents = {BaseActivityComponent.class})
public abstract class AbstractAllActivityModule {
@ContributesAndroidInjector(modules = MainActivityModule.class)
abstract MainActivity contributesMainActivityInjector();
@ContributesAndroidInjector(modules = SplashActivityModule.class)
abstract SplashActivity contributesSplashActivityInjector();
// 一系列的对应Activity的contributesxxxActivityInjector
...
}
在注释1处用subcomponents来表明开放全部依靠给AbstractAllActivityModule,运用Subcomponent的重要原因是它将运用的不同部分封装起来了。@AppComponent担任保护同享的数据和方针,而不同处则由各自的@Subcomponent保护。
2.3.接着,装备项目的Application。
public class WanAndroidApp extends Application implements HasActivityInjector {
// 3
@Inject
DispatchingAndroidInjector<Activity> mAndroidInjector;
private static volatile AppComponent appComponent;
@Override
public void onCreate() {
super.onCreate();
...
// 1
appComponent = DaggerAppComponent.builder()
.build();
// 2
appComponent.inject(this);
...
}
...
// 4
@Override
public AndroidInjector<Activity> activityInjector() {
return mAndroidInjector;
}
}
首要,在注释1处,运用AppModule模块和httpModule模块构建出AppComponent的完成类DaggerAppComponent。这儿看一下AppComponent的装备代码:
@Singleton
@Component(modules = {AndroidInjectionModule.class,
AndroidSupportInjectionModule.class,
AbstractAllActivityModule.class,
AbstractAllFragmentModule.class,
AbstractAllDialogFragmentModule.class}
)
public interface AppComponent {
/**
* 注入WanAndroidApp实例
*
* @param wanAndroidApp WanAndroidApp
*/
void inject(WanAndroidApp wanAndroidApp);
...
}
能够看到,AppComponent依靠了AndroidInjectionModule模块,它包含了一些根底装备的绑定设置,如activityInjectorFactories、fragmentInjectorFactories等等,而AndroidSupportInjectionModule模块显然便是多了一个supportFragmentInjectorFactories的绑定设置,activityInjectorFactories的内容如所示:
@Beta
@Module
public abstract class AndroidInjectionModule {
@Multibinds
abstract Map<Class<? extends Activity>, AndroidInjector.Factory<? extends Activity>>
activityInjectorFactories();
@Multibinds
abstract Map<Class<? extends Fragment>, AndroidInjector.Factory<? extends Fragment>>
fragmentInjectorFactories();
...
}
接着,下面依靠的AbstractAllActivityModule、 AbstractAllFragmentModule、AbstractAllDialogFragmentModule则是为项目的一切Activity、Fragment、DialogFragment供给的一致基类笼统Module,这儿看下AbstractAllActivityModule的装备:
@Module(subcomponents = {BaseActivityComponent.class})
public abstract class AbstractAllActivityModule {
@ContributesAndroidInjector(modules = MainActivityModule.class)
abstract MainActivity contributesMainActivityInjector();
@ContributesAndroidInjector(modules = SplashActivityModule.class)
abstract SplashActivity contributesSplashActivityInjector();
...
}
能够看到,项目下的一切xxxActiviity都有对应的contributesxxxActivityInjector()办法供给实例注入。并且,留意到AbstractAllActivityModule这个模块依靠的 subcomponents为BaseActivityComponent,前面说过了,每一个承继于BaseActivity的Activity都承继于BaseActivityComponent这一个subcomponents。同理,AbstractAllFragmentModule与AbstractAllDialogFragmentModule也是类似的完成形式,如下所示:
// 1
@Module(c = BaseFragmentComponent.class)
public abstract class AbstractAllFragmentModule {
@ContributesAndroidInjector(modules = CollectFragmentModule.class)
abstract CollectFragment contributesCollectFragmentInject();
@ContributesAndroidInjector(modules = KnowledgeFragmentModule.class)
abstract KnowledgeHierarchyFragment contributesKnowledgeHierarchyFragmentInject();
...
}
// 2
@Module(subcomponents = BaseDialogFragmentComponent.class)
public abstract class AbstractAllDialogFragmentModule {
@ContributesAndroidInjector(modules = SearchDialogFragmentModule.class)
abstract SearchDialogFragment contributesSearchDialogFragmentInject();
@ContributesAndroidInjector(modules = UsageDialogFragmentModule.class)
abstract UsageDialogFragment contributesUsageDialogFragmentInject();
}
留意到注释1和注释2处的代码,AbstractAllFragmentModule和AbstractAllDialogFragmentModule的subcomponents为BaseFragmentComponent、BaseDialogFragmentComponent,很显然,同AbstractAllActivityModule的子组件BaseActivityComponent一样,它们都是作为一个通用的子组件。
然后,回到咱们装备项目下的Application下面的注释2处的代码,在这儿运用了榜首步Dagger为咱们构建的DaggerAppComponent方针将当期的Application实例注入了进去,交给了Dagger这个依靠大管家去办理。终究,Dagger2内部创立的mAndroidInjector方针会在注释3处的当地进行实例赋值。在注释4处,完成HasActivityInjector接口,重写activityInjector()办法,将咱们上面得到的mAndroidInjector方针回来。这儿的mAndroidInjector是一个类型为DispatchingAndroidInjector的方针,能够这样理解它:它能够履行Android结构下的中心成员如Activity、Fragment的成员注入,在咱们项目下的Application中将DispatchingAndroidInjector的泛型指定为Activity就说明它承担起了一切Activity成员依靠的注入。那么,怎么指定某一个Activity能被纳入DispatchingAndroidInjector这个一切Activity的依靠总管的口袋中呢?接着看运用过程4。
2.4.终究,将方针Activity纳入Activity依靠分配总管DispatchingAndroidInjector的囊中。
很简单,只需在方针Activity的onCreate()办法前的super.onCreate(savedInstanceState)前装备一行代码 AndroidInjection.inject(this),如下所示:
public abstract class BaseActivity<T extends AbstractPresenter> extends AbstractSimpleActivity implements
AbstractView {
...
@Inject
protected T mPresenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
AndroidInjection.inject(this);
super.onCreate(savedInstanceState);
}
...
}
这儿运用了@Inject表明晰需求注入mPresenter实例,然后,咱们需求在详细的Presenter类的结构办法上运用@Inject供给根据当时结构办法的mPresenter实例,如下所示:
public class MainPresenter extends BasePresenter<MainContract.View> implements MainContract.Presenter {
...
@Inject
MainPresenter(DataManager dataManager) {
super(dataManager);
this.mDataManager = dataManager;
}
...
}
从上面的运用流程中,有三个要害的中心完成是咱们需求了解的,如下所示:
- 1、appComponent = DaggerAppComponent.builder().build()这句代码怎么构建出DaggerAPPComponent的?
- 2、appComponent.inject(this)是怎么将mAndroidInjector实例赋值给当时的Application的?
- 3、在方针Activity下的AndroidInjection.inject(this)这句代码是怎么将当时Activity方针纳入依靠分配总管DispatchingAndroidInjector囊中的呢?
下面咱们逐一地来探索其间的微妙~
3.源码剖析
3.1.DaggerAppComponent.builder().build()是怎么构建出DaggerAPPComponent的?
首要,看到DaggerAppComponent的builder()办法:
public static Builder builder() {
return new Builder();
}
里边直接回来了一个新建的Builder静态内部类方针,看看它的结构办法中做了什么:
public static final class Builder {
private Builder() {}
...
}
看来,Builder的默认结构办法什么也没有做,那么,真实的完成肯定在Builder方针的build()办法中,接着看到build()办法。
public static final class Builder {
...
public AppComponent build() {
return new DaggerAppComponent(this);
}
...
}
在Builder的build()办法中直接回来了新建的DaggerAppComponent方针。下面,看看DaggerAppComponent的结构办法:
private DaggerAppComponent(Builder builder) {
initialize(builder);
}
在DaggerAppComponent的结构办法中调用了initialize办法,望文生义,它便是真实初始化项目大局依靠装备的当地了,下面,来看看它内部的完成:
private void initialize(final Builder builder) {
// 1
this.mainActivitySubcomponentBuilderProvider =
new Provider<
AbstractAllActivityModule_ContributesMainActivityInjector.MainActivitySubcomponent
.Builder>() {
@Override
public AbstractAllActivityModule_ContributesMainActivityInjector.MainActivitySubcomponent
.Builder
get() {
// 2
return new MainActivitySubcomponentBuilder();
}
};
// 一系列xxxActivitySubcomponentBuilderProvider的创立赋值代码块
...
}
在注释1处,新建了一个mainActivit的子组件结构器实例供给者Provider。在注释2处,运用匿名内部类的办法重写了该Provider的get()办法,回来一个新创立好的MainActivitySubcomponentBuilder方针。很显然,它便是担任创立办理MAinActivity中所需依靠的Subcomponent制作者。接下来重点来剖析下MainActivitySubcomponentBuilder这个类的效果。
// 1
private final class MainActivitySubcomponentBuilder
extends AbstractAllActivityModule_ContributesMainActivityInjector.MainActivitySubcomponent
.Builder {
private MainActivity seedInstance;
@Override
public AbstractAllActivityModule_ContributesMainActivityInjector.MainActivitySubcomponent
build() {
if (seedInstance == null) {
throw new IllegalStateException(MainActivity.class.getCanonicalName() + " must be set");
}
// 2
return new MainActivitySubcomponentImpl(this);
}
@Override
public void seedInstance(MainActivity arg0) {
// 3
this.seedInstance = Preconditions.checkNotNull(arg0);
}
}
首要,在注释1处,MainActivitySubcomponentBuilder承继了AbstractAllActivityModule_ContributesMainActivityInjector内部的子组件MainActivitySubcomponent的内部的子组件制作者类Builder,如下所示:
@Subcomponent(modules = MainActivityModule.class)
public interface MainActivitySubcomponent extends AndroidInjector<MainActivity> {
@Subcomponent.Builder
abstract class Builder extends
AndroidInjector.Builder<MainActivity> {}
}
能够看到,这个子组件制作者Builder又承继了AndroidInjector的笼统内部类Builder,那么,这个AndroidInjector究竟是什么呢?
望文生义,AndroidInjector是一个Android注射器,它为每一个详细的子类型,即中心Android类型Activity和Fragment履行成员注入。
接下来剖析下AndroidInjector的内部完成,源码如下所示:
public interface AndroidInjector<T> {
void inject(T instance);
// 1
interface Factory<T> {
AndroidInjector<T> create(T instance);
}
// 2
abstract class Builder<T> implements AndroidInjector.Factory<T> {
@Override
public final AndroidInjector<T> create(T instance) {
seedInstance(instance);
return build();
}
@BindsInstance
public abstract void seedInstance(T instance);
public abstract AndroidInjector<T> build();
}
}
在注释1处,运用了笼统工厂形式,用来创立一个详细的Activity或Fragment类型的AndroidInjector实例。注释2处,Builder完成了AndroidInjector.Factory,它是一种Subcomponent.Builder的通用完成形式,在重写的create()办法中,进行了实例保存seedInstance()和详细Android中心类型的构建。
接着,咱们回到MainActivitySubcomponentBuilder类,能够看到,它完成了AndroidInjector.Builder的seedInstance()和build()办法。在注释3处首要播种了MainActivity的实例,然后 在注释2处新建了一个MainActivitySubcomponentImpl方针回来。咱们看看MainActivitySubcomponentImpl这个类是怎么将mPresenter依靠注入的,相关源码如下:
private final class MainActivitySubcomponentImpl
implements AbstractAllActivityModule_ContributesMainActivityInjector
.MainActivitySubcomponent {
private MainPresenter getMainPresenter() {
// 2
return MainPresenter_Factory.newMainPresenter(
DaggerAppComponent.this.provideDataManagerProvider.get());
}
@Override
public void inject(MainActivity arg0) {
// 1
injectMainActivity(arg0);
}
private MainActivity injectMainActivity(MainActivity instance) {
// 3
BaseActivity_MembersInjector
.injectMPresenter(instance, getMainPresenter());
return instance;
}
在注释1处,MainActivitySubcomponentImpl完成了AndroidInjector接口的inject()办法,在injectMainActivity()首要调用getMainPresenter()办法从MainPresenter_Factory工厂类中新建了一个MainPresenter方针。咱们看看MainPresenter的newMainPresenter()办法:
public static MainPresenter newMainPresenter(DataManager dataManager) {
return new MainPresenter(dataManager);
}
这儿直接新建了一个MainPresenter。然后咱们回到MainActivitySubcomponentImpl类的注释3处,持续调用了BaseActivity_MembersInjector的injectMPresenter()办法,望文生义,能够猜到,它是BaseActivity的成员注射器,持续看看injectMPresenter()内部:
public static <T extends AbstractPresenter> void injectMPresenter(
BaseActivity<T> instance, T mPresenter) {
instance.mPresenter = mPresenter;
}
能够看到,这儿直接将需求的mPresenter实例赋值给了BaseActivity的mPresenter,当然,这儿其实是指的BaseActivity的子类MainActivity,其它的xxxActivity的依靠办理机制都是如此。
3.2.appComponent.inject(this)是怎么将mAndroidInjector实例赋值给当时的Application的?
咱们持续检查appComponent的inject()办法:
@Override
public void inject(WanAndroidApp wanAndroidApp) {
injectWanAndroidApp(wanAndroidApp);
}
在inject()办法里调用了injectWanAndroidApp(),持续检查injectWanAndroidApp()办法:
private WanAndroidApp injectWanAndroidApp(WanAndroidApp instance) {
WanAndroidApp_MembersInjector.injectMAndroidInjector(
instance,
getDispatchingAndroidInjectorOfActivity());
return instance;
}
首要,履行getDispatchingAndroidInjectorOfActivity()办法得到了一个Activity类型的DispatchingAndroidInjector方针,持续检查getDispatchingAndroidInjectorOfActivity()办法:
private DispatchingAndroidInjector<Activity> getDispatchingAndroidInjectorOfActivity() {
return DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector(
getMapOfClassOfAndProviderOfFactoryOf());
}
在getDispatchingAndroidInjectorOfActivity()办法里边,首要调用了getMapOfClassOfAndProviderOfFactoryOf()办法,咱们看到这个办法:
private Map<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>>
getMapOfClassOfAndProviderOfFactoryOf() {
return MapBuilder
.<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>>
newMapBuilder(8)
.put(MainActivity.class, (Provider) mainActivitySubcomponentBuilderProvider)
.put(SplashActivity.class, (Provider) splashActivitySubcomponentBuilderProvider)
.put(ArticleDetailActivity.class,
(Provider) articleDetailActivitySubcomponentBuilderProvider)
.put(KnowledgeHierarchyDetailActivity.class,
(Provider) knowledgeHierarchyDetailActivitySubcomponentBuilderProvider)
.put(LoginActivity.class, (Provider) loginActivitySubcomponentBuilderProvider)
.put(RegisterActivity.class, (Provider) registerActivitySubcomponentBuilderProvider)
.put(AboutUsActivity.class, (Provider) aboutUsActivitySubcomponentBuilderProvider)
.put(SearchListActivity.class, (Provider) searchListActivitySubcomponentBuilderProvider)
.build();
}
能够看到,这儿新建了一个制作者形式完成的MapBuilder,并且一同制定了固定容量为8,将项目下运用了AndroidInjection.inject(mActivity)办法的8个Activity对应的xxxActivitySubcomponentBuilderProvider保存起来。
咱们再回到getDispatchingAndroidInjectorOfActivity()办法,这儿将上面得到的Map容器传入了DispatchingAndroidInjector_Factory的newDispatchingAndroidInjector()办法中,这儿应该便是新建DispatchingAndroidInjector的当地了。咱们点进去看看:
public static <T> DispatchingAndroidInjector<T> newDispatchingAndroidInjector(
Map<Class<? extends T>, Provider<AndroidInjector.Factory<? extends T>>> injectorFactories) {
return new DispatchingAndroidInjector<T>(injectorFactories);
}
在这儿,公然新建了一个DispatchingAndroidInjector方针。持续看看DispatchingAndroidInjector的结构办法:
@Inject
DispatchingAndroidInjector(
Map<Class<? extends T>, Provider<AndroidInjector.Factory<? extends T>>> injectorFactories) {
this.injectorFactories = injectorFactories;
}
这儿仅仅是将传进来的Map容器保存起来了。
咱们再回到WanAndroidApp_MembersInjector的injectMAndroidInjector()办法,将上面得到的DispatchingAndroidInjector实例传入,持续检查injectMAndroidInjector()这个办法:
public static void injectMAndroidInjector(
WanAndroidApp instance, DispatchingAndroidInjector<Activity> mAndroidInjector) {
instance.mAndroidInjector = mAndroidInjector;
}
能够看到,终究在WanAndroidApp_MembersInjector的injectMAndroidInjector()办法中,直接将新建好的DispatchingAndroidInjector实例赋值给了WanAndroidApp的mAndroidInjector。
3.3.在方针Activity下的AndroidInjection.inject(this)这句代码是怎么将当时Activity方针纳入依靠分配总管DispatchingAndroidInjector囊中的呢?
首要,咱们看到AndroidInjection.inject(this)这个办法:
public static void inject(Activity activity) {
checkNotNull(activity, "activity");
// 1
Application application = activity.getApplication();
if (!(application instanceof HasActivityInjector)) {
throw new RuntimeException(
String.format(
"%s does not implement %s",
application.getClass().getCanonicalName(),
HasActivityInjector.class.getCanonicalName()));
}
// 2
AndroidInjector<Activity> activityInjector =
((HasActivityInjector) application).activityInjector();
checkNotNull(activityInjector, "%s.activityInjector() returned null", application.getClass());
// 3
activityInjector.inject(activity);
}
在注释1处,会先判别当时的application是否完成了HasActivityInjector这个接口,假如没有,则抛出RuntimeException。假如有,会持续在注释2处调用application的activityInjector()办法得到DispatchingAndroidInjector实例。终究,在注释3处,会将当时的activity实例传入activityInjector的inject()办法中。咱们持续检查inject()办法:
@Override
public void inject(T instance) {
boolean wasInjected = maybeInject(instance);
if (!wasInjected) {
throw new IllegalArgumentException(errorMessageSuggestions(instance));
}
}
DispatchingAndroidInjector的inject()办法,它的效果便是给传入的instance实例履行成员注入。详细在这个事例中,其实便是担任将创立好的Presenter实例赋值给BaseActivity方针 的mPresenter大局变量。在inject()办法中,又调用了maybeInject()办法,咱们持续检查它:
@CanIgnoreReturnValue
public boolean maybeInject(T instance) {
// 1
Provider<AndroidInjector.Factory<? extends T>> factoryProvider =
injectorFactories.get(instance.getClass());
if (factoryProvider == null) {
return false;
}
@SuppressWarnings("unchecked")
// 2
AndroidInjector.Factory<T> factory = (AndroidInjector.Factory<T>) factoryProvider.get();
try {
// 3
AndroidInjector<T> injector =
checkNotNull(
factory.create(instance), "%s.create(I) should not return null.", factory.getClass());
// 4
injector.inject(instance);
return true;
} catch (ClassCastException e) {
...
}
}
在注释1处,咱们从injectorFactories(前面得到的Map容器)中依据当时Activity实例拿到了factoryProvider方针,这儿咱们详细一点,看到MainActivity对应的factoryProvider,也便是咱们研究的榜首个问题中的mainActivitySubcomponentBuilderProvider:
private void initialize(final Builder builder) {
this.mainActivitySubcomponentBuilderProvider =
new Provider<
AbstractAllActivityModule_ContributesMainActivityInjector.MainActivitySubcomponent
.Builder>() {
@Override
public AbstractAllActivityModule_ContributesMainActivityInjector.MainActivitySubcomponent
.Builder
get() {
return new MainActivitySubcomponentBuilder();
}
};
...
}
在maybeInject()办法的注释2处,调用了mainActivitySubcomponentBuilderProvider的get()办法得到了一个新建的MainActivitySubcomponentBuilder方针。在注释3处履行了它的create办法,create()办法的详细完成在AndroidInjector的内部类Builder中:
abstract class Builder<T> implements AndroidInjector.Factory<T> {
@Override
public final AndroidInjector<T> create(T instance) {
seedInstance(instance);
return build();
}
看到这儿,我相信看过榜首个问题的同学已经理解后边是怎么回事了。在create()办法中,咱们首要MainActivitySubcomponentBuilder的seedInstance()将MainActivity实例注入,然后再调用它的build()办法新建了一个MainActivitySubcomponentImpl实例回来。
终究,在注释4处,履行了MainActivitySubcomponentImpl的inject()办法:
private final class MainActivitySubcomponentImpl
implements AbstractAllActivityModule_ContributesMainActivityInjector
.MainActivitySubcomponent {
private MainPresenter getMainPresenter() {
// 2
return MainPresenter_Factory.newMainPresenter(
DaggerAppComponent.this.provideDataManagerProvider.get());
}
@Override
public void inject(MainActivity arg0) {
// 1
injectMainActivity(arg0);
}
private MainActivity injectMainActivity(MainActivity instance) {
// 3
BaseActivity_MembersInjector
.injectMPresenter(instance, getMainPresenter());
return instance;
}
这儿的逻辑已经在问题一的终究部分详细讲解了,终究,会在注释3处调用BaseActivity_MembersInjector的injectMPresenter()办法:
public static <T extends AbstractPresenter> void injectMPresenter(
BaseActivity<T> instance, T mPresenter) {
instance.mPresenter = mPresenter;
}
这样,就将mPresenter方针赋值给了当时Activity方针的mPresenter大局变量中了。至此,Dagger.Android的中心源码剖析就完毕了。
相比于ButterKnife,Dagger是一个锋利的大局依靠注入办理结构,它主要用来办理方针的依靠联系和生命周期,当项目越来越大时,类之间的调用层次会越来越深,并且有些类是Activity或Fragment,有些是单例,并且它们的生命周期不一致,所以创立所需方针时需求处理的各个方针的依靠联系和生命周期时的使命会很繁重。因此,运用Dagger会大大减轻这方面的作业量。尽管它的学习本钱比较高,并且需求写必定的模板类,可是,关于越大的项目来说,Dagger越值得被需求。
重视大众号:Android苦做舟
解锁 《Android十大板块文档》,让学习更靠近未来实战。已构成PDF版
内容如下:
1.2022最新Android11位大厂面试专题,128道附答案
2.音视频大合集,从初中高到面试包罗万象
3.Android车载运用大合集,从零开端一同学
4.功能优化大合集,离别优化烦恼
5.Framework大合集,从里到外剖析的明理解白
6.Flutter大合集,进阶Flutter高级工程师
7.compose大合集,拥抱新技术
8.Jetpack大合集,全家桶一次吃个够
9.架构大合集,轻松应对作业需求
10.Android根底篇大合集,根基安定楼房平地起
收拾不易,重视一下吧。ღ( ・ᴗ・` )