ㄷㅣㅆㅣ's Amusement
[Android/Java] Glide, source analysis. -- 2. Flow 본문
[Android/Java] Glide, source analysis. -- 2. Flow
반응형
Glide
You will Save yourself a lot of time & headache.
지난 포스팅에서는....
- Glide를 사용하는 것이 안드로이드 개발에서는 매우 일반적이 되어버렸고, 그때문에 더이상 이미지에 의한 OOM(Out Of Memory)문제를 겪지 않겠지만, 그래도 알고 쓰는것과 모르고 쓰는 것에는 매우 큰 차이가 있다.
- 또한 Glide가 아무리 안정적이더라도 신이 인간을 어여삐 여겨 내려준 코드가 아닌 이상 왕도는 없으므로, 프로젝트 성격에 의해 커스터마이징 할 필요가 있을지도 모르니 Flow라도 알아보자.
- 이번 시리즈는 몇편이 마지막일지도 모르겠고, 참고할 자료라고는 오로지 소스코드밖에 없으니... 조바심 내지 않고 차근차근 써내려가보겠다.
- 시리즈의 2번째인 이번 포스팅은 다소 성의없어보일 수도 있겠으나... Flow를 설명하기에 이보다 명료한 방법이 없을 것 같으니 궁금한 점이 생기면 언제든 댓글 달아주세요.
- When the operation started to run.1234Glide.with(context).load(/*IMAGE_PATH*/).into(/*IMAGE_VIEW*/);
cs
- with
- get
- Glide.get —> createGlide
- to return created glide
- RequestManager 생성
- Glide가 호출된 액티비티의 fragment를 RequestManagerFragment로 감싸고, lifecycle 리스너를 등록한다.
- ConnectivityMonitor를 생성
- glide객체에 자신을 등록한다. (glide.setRequestManager)
- to return requestManager
- to return requestManager
- to return requestManager
- requestManager에 어떻게 불러올 것인지 세팅한다.
- requestBuilder 생성
- to return requestBuilder
- to return requestBuilder
- target에 이미지를 할당한다.
- target이 기존 작업을 가지고있으면 취소
- request를 생성
- status를 pending으로 설정
- to return request
- track()
- TargetTracker에 target(ImageViewTarget)을 등록
- RequestTracker에 request를 등록
- begin()
- status를 WAITING_FOR_SIZE로 변경
- 기존에 width, height를 계산했었다면(?) onSizeReady호출, 아니라면 계산 후 호출
- onSizeReady()에서는 status를 RUNNING으로 변경하고, engine.load() 호출.
- ImageViewTarget에 PlaceHolder 세팅
- load() (이 부분부터는 3부에서 다룹니다)
- EngineJob을 만든다
- DecodeJob을 만든다
- EngineJob으로 Decode한다. (왜? --> [Android/Java] 병렬 프로그래밍 : Executor Framework에대한 고찰 참고.)
- ModelLoader에서 decode
- 복잡한 decode step을 수행하고 Request의 onResourceReady() 호출
- ImageViewTarget의 setResource()를 호출하여 이미제 세팅
---------------- 이하 Call Sequence에 의한 source code ---------------------
Get suitable "Request Manager" (1~8)
1234567// Glide.java// ".with()"public static RequestManager with(Context context) {RequestManagerRetriever retriever = RequestManagerRetriever.get();return retriever.get(context);}cs - Using "Request Manager Retriever"123456789101112131415161718192021222324252627282930313233343536373839// RequestManagerRetriever.javapublic RequestManager get(Context context) {if (context == null) {throw new IllegalArgumentException("You cannot start a load on a null Context");} else if (Util.isOnMainThread() && !(context instanceof Application)) {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());}}return getApplicationManager(context);}public RequestManager get(FragmentActivity activity) {if (Util.isOnBackgroundThread()) {return get(activity.getApplicationContext());} else {assertNotDestroyed(activity);FragmentManager fm = activity.getSupportFragmentManager();return supportFragmentGet(activity, fm, null);}}public RequestManager get(Fragment fragment) {if (fragment.getActivity() == null) {throw new IllegalArgumentException("You cannot start a load on a fragment before it is attached");}if (Util.isOnBackgroundThread()) {return get(fragment.getActivity().getApplicationContext());} else {FragmentManager fm = fragment.getChildFragmentManager();return supportFragmentGet(fragment.getActivity(), fm, fragment);}}
cs Making RequestBuilder and add the transition options then object loading (9~12)
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051// RequestManager.java// ".load"/*** Returns a request builder to load the given {@link java.lang.String}. signature.** <p> Note - this method caches data using only the given String as the cache key. If the data is* a Uri outside of your control, or you otherwise expect the data represented by the given String* to change without the String identifier changing, Consider using* {@link com.bumptech.glide.request.BaseRequestOptions#signature(com.bumptech.glide.load.Key)} to* mixin a signature you create that identifies the data currently at the given String that will* invalidate the cache if that data changes. Alternatively, using* {@link com.bumptech.glide.load.engine.DiskCacheStrategy#NONE} and/or* {@link com.bumptech.glide.request.BaseRequestOptions#skipMemoryCache(boolean)} may be* appropriate.* </p>** @see #load(Object)** @param string A file path, or a uri or url handled by* {@link com.bumptech.glide.load.model.UriLoader}.*/public RequestBuilder<TranscodeType> load(@Nullable String string) {return loadGeneric(string);}/*** Attempts to always load the resource using any registered {@link* com.bumptech.glide.load.ResourceDecoder}s that can decode any subclass of {@link Drawable}.** <p> By default, may return either a {@link android.graphics.drawable.BitmapDrawable} or {@link* GifDrawable}, but if additional decoders are registered for other {@link Drawable} subclasses,* any of those subclasses may also be returned. </p>** @return A new request builder for loading a {@link Drawable}.*/public RequestBuilder<Drawable> asDrawable() {return as(Drawable.class).transition(new DrawableTransitionOptions());}/*** A helper method equivalent to calling {@link #asDrawable()} and then {@link* RequestBuilder#load(Object)} with the given model.** @return A new request builder for loading a {@link Drawable} using the given model.*/public RequestBuilder<Drawable> load(@Nullable Object model) {return asDrawable().load(model);}cs - To Request to load123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172// RequestBuilder.java// ".load"/*** Set the target the resource will be loaded into.** @param target The target to load the resource into.* @return The given target.* @see RequestManager#clear(Target)*/public <Y extends Target<TranscodeType>> Y into(@NonNull Y target) {Util.assertMainThread();Preconditions.checkNotNull(target);if (!isModelSet) {throw new IllegalArgumentException("You must call #load() before calling #into()");}Request previous = target.getRequest();if (previous != null) {requestManager.clear(target);}requestOptions.lock();Request request = buildRequest(target);target.setRequest(request);requestManager.track(target, request);return target;}/*** Sets the {@link ImageView} the resource will be loaded into, cancels any existing loads into* the view, and frees any resources Glide may have previously loaded into the view so they may be* reused.** @see RequestManager#clear(Target)** @param view The view to cancel previous loads for and load the new resource into.* @return The* {@link com.bumptech.glide.request.target.Target} used to wrap the given {@link ImageView}.*/public Target<TranscodeType> into(ImageView view) {Util.assertMainThread();Preconditions.checkNotNull(view);if (!requestOptions.isTransformationSet()&& requestOptions.isTransformationAllowed()&& view.getScaleType() != null) {if (requestOptions.isLocked()) {requestOptions = requestOptions.clone();}switch (view.getScaleType()) {case CENTER_CROP:requestOptions.optionalCenterCrop(context);break;case CENTER_INSIDE:requestOptions.optionalCenterInside(context);break;case FIT_CENTER:case FIT_START:case FIT_END:requestOptions.optionalFitCenter(context);break;//$CASES-OMITTED$default:// Do nothing.}}return into(context.buildImageViewTarget(view, transcodeClass));}
cs
- Build Request (14~15)1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465// RequestBuilder.javaprivate Request obtainRequest(Target<TranscodeType> target,BaseRequestOptions<?> requestOptions, RequestCoordinator requestCoordinator,TransitionOptions<?, ? super TranscodeType> transitionOptions, Priority priority,int overrideWidth, int overrideHeight) {requestOptions.lock();return SingleRequest.obtain(context,model,transcodeClass,requestOptions,overrideWidth,overrideHeight,priority,target,requestListener,requestCoordinator,context.getEngine(),transitionOptions.getTransitionFactory());}private Request buildRequest(Target<TranscodeType> target) {return buildRequestRecursive(target, null, transitionOptions, requestOptions.getPriority(),requestOptions.getOverrideWidth(),requestOptions.getOverrideHeight());}private Request buildRequestRecursive(Target<TranscodeType> target,@Nullable ThumbnailRequestCoordinator parentCoordinator,TransitionOptions<?, ? super TranscodeType> transitionOptions,Priority priority, int overrideWidth, int overrideHeight) {// Base case: no thumbnail.return obtainRequest(target, requestOptions, parentCoordinator, transitionOptions, priority,overrideWidth, overrideHeight);}/*** Set the target the resource will be loaded into.** @param target The target to load the resource into.* @return The given target.* @see RequestManager#clear(Target)*/public <Y extends Target<TranscodeType>> Y into(@NonNull Y target) {Util.assertMainThread();Preconditions.checkNotNull(target);if (!isModelSet) {throw new IllegalArgumentException("You must call #load() before calling #into()");}Request previous = target.getRequest();if (previous != null) {requestManager.clear(target);}requestOptions.lock();Request request = buildRequest(target);target.setRequest(request);requestManager.track(target, request);return target;}
cs - Add track (17~18)12345// RequestManager.javavoid track(Target<?> target, Request request) {targetTracker.track(target);requestTracker.runRequest(request);}
cs - begin request (19)1234567891011/*** Starts tracking the given request.*/public void runRequest(Request request) {requests.add(request);if (!isPaused) {request.begin();} else {pendingRequests.add(request);}}
cs - load(20)12345678910111213141516171819202122232425262728293031323334// SingleReqeust.java@Overridepublic void begin() {stateVerifier.throwIfRecycled();startTime = LogTime.getLogTime();if (model == null) {if (Util.isValidDimensions(overrideWidth, overrideHeight)) {width = overrideWidth;height = overrideHeight;}// Only log at more verbose log levels if the user has set a fallback drawable, because// fallback Drawables indicate the user expects null models occasionally.int logLevel = getFallbackDrawable() == null ? Log.WARN : Log.DEBUG;onLoadFailed(new GlideException("Received null model"), logLevel);return;}status = Status.WAITING_FOR_SIZE;if (Util.isValidDimensions(overrideWidth, overrideHeight)) {onSizeReady(overrideWidth, overrideHeight);} else {target.getSize(this);}if ((status == Status.RUNNING || status == Status.WAITING_FOR_SIZE)&& canNotifyStatusChanged()) {target.onLoadStarted(getPlaceholderDrawable());}if (Log.isLoggable(TAG, Log.VERBOSE)) {logV("finished run method in " + LogTime.getElapsedMillis(startTime));}}
cs
%% 모든 소스코드는 이곳에서 다운로드 할 수 있습니다 %%
반응형
'Programming > Android' 카테고리의 다른 글
[Android/Java] Glide, source analysis -- 4. ModelLoader & DataFetcher (0) | 2017.01.04 |
---|---|
[Android/Java] Glide, source analysis. -- 3. EngineJob & DecodeJob (0) | 2016.12.19 |
[Android/Java] 병렬 프로그래밍 : Executor Framework에대한 고찰 ----- 3 (0) | 2016.12.07 |
[Android/Java] 변수를 Volatile로 선언하면? (0) | 2016.12.06 |
[Android/Java] 병렬 프로그래밍 : Executor Framework에대한 고찰 ----- 2 (2) | 2016.12.05 |
Comments