Glide源碼分析之Glide和RequestManager構建過程 Glide源碼分析之自定義模塊及Glide如何觸發網絡請求(未發佈) Glide源碼分析之load(url)和into(iv)(未發佈) Glide源碼分析之緩存機制(未發佈)android
多數狀況下,使用Glide加載圖片很是簡單,一行代碼足矣:數組
Glide.with(fragment).load(myUrl).into(imageView)
複製代碼
取消加載:緩存
Glide.with(fragment).clear(imageView);
複製代碼
實際上,Glide.with() 中傳入的 Activity 或 Fragment 實例銷燬時,Glide 會自動觀察 Activity 或 Fragment 的生命週期取消加載並回收資源,實際上Glide爲了監聽Activity 或 Fragment的聲明週期會在內部添加一個fragment就是爲監聽生命週期。網絡
看一下Glide.with()的源碼:app
/**
* with方法主要的邏輯:
* 一、在1步驟中經過getRetriever獲取到在初始化Glide時建立的RequestManagerRetriever實例;
* 二、在2步驟中經過RequestManagerRetriever的get方法獲取RequestManager實例。
*
* <p>
* RequestManagerRetriever用於建立新的RequestManagers或從activity和fragment中檢索現有的RequestManagers
*
* @param context
* @return
*/
@NonNull
public static RequestManager with(@NonNull Context context) {
// 調用getRetriever獲取RequestManagerRetriever
RequestManagerRetriever requestManagerRetriever = getRetriever(context);// 1
// 調用RequestManagerRetriever的get方法,獲取RequestManager(圖片請求加載管理者)
RequestManager requestManager = requestManagerRetriever.get(context); // 2
return requestManager;
}
/**
* 請求資源使用Activityh生命週期同步
*
* @param activity
* @return
*/
@NonNull
public static RequestManager with(@NonNull Activity activity) {
return getRetriever(activity).get(activity);
}
/**
* 請求資源使用FragmentActivity生命週期同步
*/
@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {
return getRetriever(activity).get(activity);
}
/**
* 請求資源使用Fragment生命週期同步
*/
@NonNull
public static RequestManager with(@NonNull Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
/**
* 請求資源使用android.app.Fragment生命週期同步
*/
@SuppressWarnings("deprecation")
@Deprecated
@NonNull
public static RequestManager with(@NonNull android.app.Fragment fragment) {
return getRetriever(fragment.getActivity()).get(fragment);
}
/**
* 經過View去搜索其依附的Activity或者Fragment並使用它們做爲請求資源使用生命週期同步
*/
@NonNull
public static RequestManager with(@NonNull View view) {
return getRetriever(view.getContext()).get(view);
}
複製代碼
能夠看到Glide.with(context)有幾個重載的方法,Glide.with(context)方法主要的邏輯: 一、在1步驟中經過getRetriever獲取到在初始化Glide時建立的RequestManagerRetriever實例; 二、在2步驟中經過RequestManagerRetriever的get方法獲取RequestManager實例。 RequestManagerRetriever用於建立新的RequestManagers或從activity和fragment中檢索現有的RequestManagerside
Glide.with(context)最終調用getRetriever(context),而後再調用RequestManagerRetriever的實例get()方法,去獲取RequestManager對象:源碼分析
/**
* getRetriever方法主要邏輯:
* 一、在1步驟,會建立Glide實例而且初始化Glide實例,還會建立RequestManagerRetriever實例對象;
* 二、在2步驟直接返回RequestManagerRetriever實例
*
* @param context
* @return
*/
@NonNull
private static RequestManagerRetriever getRetriever(@Nullable Context context) { // 1.2
// Glide.get(context) 獲取Glide對象,包括初始化之類的配置
Glide glide = Glide.get(context);//1
// 經過Glide獲取RequestManagerRetriever
// 可能你會驚訝在哪 初始化RequestManagerRetriever的,實際上是在GlideBuilder的build方法中
RequestManagerRetriever requestManagerRetriever = glide.getRequestManagerRetriever();// 2
return requestManagerRetriever;
}
複製代碼
一、 Glide.get(context) 獲取Glide對象包括初始化之類的配置,初始化後面會講GlideBiulder; 二、經過Glide對象獲取RequestManagerRetriever, 可能你會驚訝在哪 初始化RequestManagerRetriever的,實際上是在GlideBuilder的build方法中。動畫
接下來看一下調用RequestManagerRetriever 的get方法,也是有幾個重載;ui
/**
* <p>
* 上面getRetriever(context)方法,主要是構建Glide和RequestManagerRetriever
* <p>
* RequestManagerRetriever:一組靜態方法,用於建立新的RequestManagers或從活動和片斷中檢索現有的RequestManagers。
* <p>
* 這一步就是構建RequestManager:描述圖片加載請求管理者
* <p>
* <p>
* 做用:主要是經過傳入的context構建RequestManager實例,固然你這裏可會從activity和fragment中獲取已經存在的RequestManager
* 爲何須要context?主要是構建的RequestManager即請求管理,須要感知各組件的生命週期,例如:application、activity和fragment
* <p>
* 主要的邏輯:
* 一、在1步驟中判斷是不是在主線程和是否是Application,若是咱們是在非主線程當中使用的Glide,那麼無論你是傳入的Activity仍是Fragment,都會被強制當成Application來處理
* 二、在2步驟中直接當成Application處理;
* 三、最後會經過RequestManager工廠(RequestManagerFactory)建立RequestManager實例
* <p>
* 最後:
* 雖然get方法有多個重載其實邏輯的處理只有兩種:
* 一、傳入的context是非Application參數的狀況:
* 不論是傳入的context是Activity、FragmentActivity、v4包下的Fragment、仍是app包下的Fragment,
* 最終的邏輯是同樣的,會向當前的Activity當中添加一個隱藏的Fragment。由於Glide須要感知加載的生命週期
* 二、傳入的context是Application參數的狀況,或者是在後臺線程:
* 若是傳入的context是Application或者是在後臺線程,直接就調用getApplicationManager()方法來獲取一個RequestManager對象
* <p>
* <p>
*
* <p>
* 注意這裏的get方法都是單例的
*
* @param context
* @return
*/
@NonNull
public RequestManager get(@NonNull Context context) {
if (context == null) {
throw new IllegalArgumentException("You cannot start a load on a null Context");
//若是咱們是在非主線程當中使用的Glide,那麼無論你是傳入的Activity仍是Fragment,都會被強制當成Application來處理
} else if (Util.isOnMainThread() && !(context instanceof Application)) {//1
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);// 2
}
@NonNull
public RequestManager get(@NonNull FragmentActivity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
// 獲取當前activity的FragmentManager,由於你須要爲當前activity添加隱藏的fragment
FragmentManager fm = activity.getSupportFragmentManager();
return supportFragmentGet(activity, fm, null, isActivityVisible(activity));
}
}
@NonNull
public RequestManager get(@NonNull Fragment fragment) {
Preconditions.checkNotNull(fragment.getActivity(),
"You cannot start a load on a fragment before it is attached or after it is destroyed");
if (Util.isOnBackgroundThread()) {
return get(fragment.getActivity().getApplicationContext());
} else {
FragmentManager fm = fragment.getChildFragmentManager();
return supportFragmentGet(fragment.getActivity(), fm, fragment, fragment.isVisible());
}
}
@SuppressWarnings("deprecation")
@NonNull
public RequestManager get(@NonNull Activity activity) {
if (Util.isOnBackgroundThread()) {
return get(activity.getApplicationContext());
} else {
assertNotDestroyed(activity);
android.app.FragmentManager fm = activity.getFragmentManager();
return fragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
}
}
@SuppressWarnings("deprecation")
@NonNull
public RequestManager get(@NonNull View view) {
if (Util.isOnBackgroundThread()) {
return get(view.getContext().getApplicationContext());
}
Preconditions.checkNotNull(view);
Preconditions.checkNotNull(view.getContext(),
"Unable to obtain a request manager for a view without a Context");
Activity activity = findActivity(view.getContext());
// The view might be somewhere else, like a service.
if (activity == null) {
return get(view.getContext().getApplicationContext());
}
// Support Fragments.
// Although the user might have non-support Fragments attached to FragmentActivity, searching
// for non-support Fragments is so expensive pre O and that should be rare enough that we
// prefer to just fall back to the Activity directly.
if (activity instanceof FragmentActivity) {
Fragment fragment = findSupportFragment(view, (FragmentActivity) activity);
return fragment != null ? get(fragment) : get(activity);
}
// Standard Fragments.
android.app.Fragment fragment = findFragment(view, activity);
if (fragment == null) {
return get(activity);
}
return get(fragment);
}
複製代碼
一、上面getRetriever(context)方法,主要是構建Glide和RequestManagerRetriever 二、RequestManagerRetriever:一組靜態方法,用於建立新的RequestManagers或從活動和片斷中檢索現有的RequestManagers。 三、這一步就是構建RequestManager:描述圖片加載請求管理者 四、 做用:主要是經過傳入的context構建RequestManager實例,固然你這裏可會從activity和fragment中獲取已經存在的RequestManager 五、爲何須要context?主要是構建的RequestManager即請求管理,須要感知各組件的生命週期,例如:application、activity和fragment 六、主要的邏輯:url
能夠看到在get方法中經過supportFragmentGet方法和getSupportRequestManagerFragment構建隱藏的fragment:
/**
* 主要邏輯:
* 一、搜索是否已經添加了隱藏的Fragment到當前的Activity中,若是已經添加過了是由緩存的。
* 二、若是在當前activity,已經添加了隱藏的Fragment,就嘗試從隱藏的Fragment中搜索RequestManager,
* 若是沒有找到,就調用RequestManager工廠建立一個RequestManager,並添加到隱藏的Fragment中,而後返回RequestManager實例。
* <p>
* 注意:其實一個Activity就存在一個RequestManager,它們的關係是activity-SupportRequestManagerFragment-RequestManager一一對應
*
* @param context
* @param fm
* @param parentHint
* @param isParentVisible
* @return
*/
@NonNull
private RequestManager supportFragmentGet(@NonNull Context context, @NonNull FragmentManager fm,
@Nullable Fragment parentHint, boolean isParentVisible) {
// 搜索隱藏的Fragment
SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
//從隱藏的Fragment搜索RequestManager
RequestManager requestManager = current.getRequestManager();
// 若是不存在就直接建立RequestManager並添加到隱藏的Fragment中緩存
if (requestManager == null) {
Glide glide = Glide.get(context);
requestManager = factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
current.setRequestManager(requestManager);
}
return requestManager;
}
@NonNull
private SupportRequestManagerFragment getSupportRequestManagerFragment(@NonNull final FragmentManager fm,
@Nullable Fragment parentHint, boolean isParentVisible) {
// 搜索是否已經添加了隱藏的Fragment
SupportRequestManagerFragment current = (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);//1
if (current == null) {
// 從緩存中找
current = pendingSupportRequestManagerFragments.get(fm);// 2
// 仍是沒有找到,就直接建立一個Fragment
if (current == null) {
current = new SupportRequestManagerFragment();
current.setParentFragmentHint(parentHint);
// 若是當前activity正在顯示
if (isParentVisible) {
current.getGlideLifecycle().onStart();
}
// 加入緩存
pendingSupportRequestManagerFragments.put(fm, current);
// 開始fragment事務,標誌設置爲FRAGMENT_TAG
fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
}
}
return current;
}
複製代碼
一、搜索是否已經添加了隱藏的Fragment到當前的Activity中,若是已經添加過了是由緩存的。 二、若是在當前activity,已經添加了隱藏的Fragment,就嘗試從隱藏的Fragment中搜索RequestManager, 若是沒有找到,就調用RequestManager工廠建立一個RequestManager,並添加到隱藏的Fragment中,而後返回RequestManager實例。 注意:其實一個Activity就存在一個RequestManager,它們的關係是activity-SupportRequestManagerFragment-RequestManager一一對應
到此爲止就已經建立你好RequestManager了,也就是Glide的整個構建流程完畢,有的讀者可能會發現Glide的構建怎麼沒有,下面就開始。
你們還記得 getRetriever(context)方法中有這麼一行
Glide glide = Glide.get(context);
複製代碼
咱們來看看Glide get(@NonNull Context context)源碼
private static volatile Glide glide;
/**
* Get the singleton.
* 單例雙重校驗
*/
@NonNull
public static Glide get(@NonNull Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context);
}
}
}
return glide;
}
private static void checkAndInitializeGlide(@NonNull Context context) {
if (isInitializing) {
throw new IllegalStateException("You cannot call Glide.get() in registerComponents(),"
+ " use the provided Glide instance instead");
}
isInitializing = true;
initializeGlide(context);
isInitializing = false;
}
複製代碼
這個方法首先會檢查是否已經初始化了,由於在初始化Glide的線程中,一個或多個類能夠屢次調用Glide.get(context)。 若是沒有這個檢查,那些調用可能會觸發無限遞歸。就是避免重複初始化Glide對象
下面就是Glide初始化真正的邏輯:
/**
* 首先找到@GlideModel註解生成的類GeneratedAppGlideModuleImpl
*
* @param context
* @param builder
*/
private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
//獲取 applicationContext
Context applicationContext = context.getApplicationContext();
// 找到@GlideModel註解生成的類如GeneratedAppGlideModuleImpl
GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
/**
*
*
* 會觸發每一個Module包括咱們自定義的Module中的applyOptions
*
* 在GlideBuilder中的biuld方法,每個默認配置都是判斷null,因此咱們能夠在咱們的自定義Module中修改Glide的配置
*
*/
if (annotationGeneratedModule != null) {
annotationGeneratedModule.applyOptions(applicationContext, builder);
}
// 構建Glide
Glide glide = builder.build(applicationContext);
// 註冊組件,例如:替換默認HttpUrlConnection爲OkHttp以及其餘組件,固然這些是能夠經過註解來完成的,詳細請看官方的demo
if (annotationGeneratedModule != null) {
annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
}
applicationContext.registerComponentCallbacks(glide);
Glide.glide = glide;
}
複製代碼
首先找到@GlideModel註解生成的類GeneratedAppGlideModuleImpl,而且會觸發每一個Module包括咱們自定義的Module中的applyOptions,以便咱們修改Glide的默認配置。也就是說當你調用with方法時,就已經初始化Glide
再看看initializeGlide方法中初始化相關的配置GlideBiulder,這裏使用構建模式
// 構建Glide
Glide glide = builder.build(applicationContext);
複製代碼
GlideBuilder:
private final Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions = new ArrayMap<>();
// 負責啓動負載並管理活動和緩存資源。
private Engine engine;
// Bitmap 複用池(享元模式)
private BitmapPool bitmapPool;
private ArrayPool arrayPool;
// 內存管理計算器或者策略
private MemorySizeCalculator memorySizeCalculator;
private MemoryCache memoryCache;
// Glide 資源線程池
private GlideExecutor sourceExecutor;
// 磁盤緩存線程池
private GlideExecutor diskCacheExecutor;
// 磁盤緩存工廠
private DiskCache.Factory diskCacheFactory;
// 網絡狀態監視器工廠
private ConnectivityMonitorFactory connectivityMonitorFactory;
private int logLevel = Log.INFO;
// 默認請求項
private RequestOptions defaultRequestOptions = new RequestOptions();
@Nullable
private RequestManagerFactory requestManagerFactory;
//執行動畫的線程池
private GlideExecutor animationExecutor;
private boolean isActiveResourceRetentionAllowed;
@Nullable
private List<RequestListener<Object>> defaultRequestListeners;
private boolean isLoggingRequestOriginsEnabled;
複製代碼
出了這些成員變量以外還有就是這些變量的setxx方法,我就不一一列出來,重點看看biuld方法。
/**
* 其實每次判斷是否爲null就是不該該重複初始化,這也給咱們在自定義Model修改Glide的默認配置
*
* @param context
* @return
*/
@NonNull
Glide build(@NonNull Context context) {
// 網絡資源操做線程池
if (sourceExecutor == null) {
sourceExecutor = GlideExecutor.newSourceExecutor();
}
// 磁盤緩存操做線程池,不容許進行網絡操做
if (diskCacheExecutor == null) {
diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
}
// 執行動畫操做線程池
if (animationExecutor == null) {
animationExecutor = GlideExecutor.newAnimationExecutor();
}
//內存計算器,它嘗試根據某些常量和設備屏幕密度,寬度和高度智能地肯定給定設備的高速緩存大小。
if (memorySizeCalculator == null) {
memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
}
// 設備網絡監視器
if (connectivityMonitorFactory == null) {
connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
}
// bitmap 複用池
if (bitmapPool == null) {
int size = memorySizeCalculator.getBitmapPoolSize();
if (size > 0) {
bitmapPool = new LruBitmapPool(size);
} else {
bitmapPool = new BitmapPoolAdapter();
}
}
// 暫時叫數組複用池
if (arrayPool == null) {
arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
}
// 內存緩存
if (memoryCache == null) {
memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
}
// 磁盤緩存工廠
if (diskCacheFactory == null) {
diskCacheFactory = new InternalCacheDiskCacheFactory(context);
}
// 構建一個負責啓動和加載並管理活動和緩存資源。
if (engine == null) {
engine =
new Engine(
memoryCache,
diskCacheFactory,
diskCacheExecutor,
sourceExecutor,
GlideExecutor.newUnlimitedSourceExecutor(),
animationExecutor,
isActiveResourceRetentionAllowed);
}
if (defaultRequestListeners == null) {
defaultRequestListeners = Collections.emptyList();
} else {
defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
}
//一組靜態方法,用於建立新的RequestManagers或從活動和片斷中(Retriever)檢索現有的RequestManager。
// RequestManager 描述圖片加載請求管理者,例如:感知聲明週期取消請求
RequestManagerRetriever requestManagerRetriever = new RequestManagerRetriever(requestManagerFactory);
// 建立GLide對象
return new Glide(
context,
engine,
memoryCache,
bitmapPool,
arrayPool,
requestManagerRetriever,
connectivityMonitorFactory,
logLevel,
defaultRequestOptions.lock(),
defaultTransitionOptions,
defaultRequestListeners,
isLoggingRequestOriginsEnabled);
}
複製代碼
其實Glide的構建是至關複雜的,包括各類線程池的配置以及各類複用池的構建,經過GlideBuilder構建Glide,RequestManager見名思意就是檢索RequestManager即在activity或者Fragment中檢索是否存在,不然直接建立。