前面一篇文章對Glide
第一次加載網絡圖片的流程經過源碼的方式一步步的帶你們看了下,至少對Glide的整個框架有了一個大體的認識。這篇文章咱們繼續深刻。java
這一篇主要介紹下,第一次加載圖片緩存磁盤後,從新啓動app,再次加載的時候,從磁盤讀取的過程。中間還會涉及到Glide
其餘的一些源碼內容。緩存
從磁盤加載文件,那麼確定就有把圖片存起來的這個步驟。咱們先來看看Glide
是如何把圖片存起來的。網絡
上篇文章已經簡單的介紹了,就是圖片加載成功以後從新又調用了SourceGenerator
的startNext
方法。app
public boolean startNext() {
if (dataToCache != null) {
Object data = dataToCache;
dataToCache = null;
cacheData(data);
}
...
}
複製代碼
重點就是看下cacheData
這個方法,如何去緩存圖片。上一篇文章,重在流程,因此一筆帶過了,此次咱們就繼續深刻。框架
private void cacheData(Object dataToCache) {
long startTime = LogTime.getLogTime();
try {
Encoder<Object> encoder = helper.getSourceEncoder(dataToCache);
DataCacheWriter<Object> writer =
new DataCacheWriter<>(encoder, dataToCache, helper.getOptions());
originalKey = new DataCacheKey(loadData.sourceKey, helper.getSignature());
helper.getDiskCache().put(originalKey, writer);
...
}
複製代碼
其實最主要的就是這4行代碼,咱們一個個來解析。ide
<X> Encoder<X> getSourceEncoder(X data) throws Registry.NoSourceEncoderAvailableException {
return glideContext.getRegistry().getSourceEncoder(data);
}
...
public <X> Encoder<X> getSourceEncoder(@NonNull X data) throws NoSourceEncoderAvailableException {
Encoder<X> encoder = encoderRegistry.getEncoder((Class<X>) data.getClass());
if (encoder != null) {
return encoder;
}
throw new NoSourceEncoderAvailableException(data.getClass());
}
...
public synchronized <T> Encoder<T> getEncoder(@NonNull Class<T> dataClass) {
for (Entry<?> entry : encoders) {
if (entry.handles(dataClass)) {
return (Encoder<T>) entry.encoder;
}
}
return null;
}
複製代碼
一步步跟入,就是這3個方法,總結來講,就是一開始的時候在EncoderRegistry
對象中註冊多個編碼器,經過key-value
的形式保存起來,能夠經過傳入的數據類型來獲取到本身對應的編碼器。函數
這裏就直接說下結果。前面網絡請求返回對象是ContentLengthInputStream
類型的。 fetch
本身debug一下,就會比較清楚,encoders裏面註冊了2個Encoder,分別用來解析ByteBuffer
和InputStream
。ui
很顯然,這裏返回了StreamEncoder
來處理。this
建立DataCacheWriter
把第一步獲取到的StreamEncoder
看成參數傳入。只是建立個對象,沒什麼好說的。
建立緩存的DataCacheKey key-value的方式緩存數據,這裏的key就是DataCacheKey
。
緩存數據 這裏就是重點了,開始進行磁盤緩存數據。
helper.getDiskCache().put(originalKey, writer);
複製代碼
首先咱們要知道helper.getDiskCache()
獲取到的對象是什麼。由於三方框架中會使用不少接口,因此咱們有時間直接看代碼並不能立刻知道具體對應是哪一個實現。 這裏有2個辦法。
ctrl+左鍵
一直往前找引用,找賦值的地方這裏我就不帶你們這樣一步步找了,直接看關鍵的幾個地方。 DecodeHelper->diskCacheProvider
=> DecodeJob->diskCacheProvider
=> DecodeJobFactory->diskCacheProvider
=> Engine->diskCacheProvider
這裏就發現了
this.diskCacheProvider = new LazyDiskCacheProvider(diskCacheFactory);
複製代碼
可是這裏又有一個參數diskCacheFactory
咱們還須要看這個是那裏來的,繼續往前找 Engine->diskCacheFactory
=> GlideBuilder->diskCacheFactory
這裏發現了
if (diskCacheFactory == null) {
diskCacheFactory = new InternalCacheDiskCacheFactory(context);
}
複製代碼
在構建Glide
對象的時候若是沒有傳入diskCacheFactory
,那麼這裏就會默認生成一個InternalCacheDiskCacheFactory
。
好了這樣咱們就能夠從新再來看下
helper.getDiskCache().put(originalKey, writer);
複製代碼
其實就是
helper.getDiskCache().put(originalKey, writer);
...
DiskCache getDiskCache() {
return diskCacheProvider.getDiskCache();
}
...
@Override
public DiskCache getDiskCache() {
if (diskCache == null) {
synchronized (this) {
if (diskCache == null) {
diskCache = factory.build();
}
if (diskCache == null) {
diskCache = new DiskCacheAdapter();
}
}
}
return diskCache;
}
複製代碼
前面咱們已經一氣呵成,把factory
也找出來了,也就是InternalCacheDiskCacheFactory
。
public final class InternalCacheDiskCacheFactory extends DiskLruCacheFactory //build方法在DiskLruCacheFactory裏面 public DiskCache build() {
File cacheDir = cacheDirectoryGetter.getCacheDirectory();
if (cacheDir == null) {
return null;
}
if (!cacheDir.mkdirs() && (!cacheDir.exists() || !cacheDir.isDirectory())) {
return null;
}
return DiskLruCacheWrapper.create(cacheDir, diskCacheSize);
}
複製代碼
這裏就是建立緩存的文件。
public final class InternalCacheDiskCacheFactory extends DiskLruCacheFactory {
public InternalCacheDiskCacheFactory(Context context) {
this(context, "image_manager_disk_cache", 262144000L);
}
public InternalCacheDiskCacheFactory(Context context, long diskCacheSize) {
this(context, "image_manager_disk_cache", diskCacheSize);
}
public InternalCacheDiskCacheFactory(final Context context, final String diskCacheName, long diskCacheSize) {
super(new CacheDirectoryGetter() {
public File getCacheDirectory() {
File cacheDirectory = context.getCacheDir();
if (cacheDirectory == null) {
return null;
} else {
return diskCacheName != null ? new File(cacheDirectory, diskCacheName) : cacheDirectory;
}
}
}, diskCacheSize);
}
}
複製代碼
在InternalCacheDiskCacheFactory
能夠看出圖片緩存的文件路徑。
就是在context.getCacheDir()
裏面的image_manager_disk_cache
文件夾。 咱們能夠發現,我這個設備裏面已經緩存了一個文件。
若是說,你不想存在這個文件,你就自定義一個DiskLruCacheFactory
在前面咱們會發現最後在build方法中建立的是
return DiskLruCacheWrapper.create(cacheDir, diskCacheSize);
複製代碼
一個DiskLruCacheWrapper
對象,因此前面緩存的時候也是調用了DiskLruCacheWrapper
的put
方法。
public void put(Key key, Writer writer) {
DiskLruCache diskCache = getDiskCache();
Value current = diskCache.get(safeKey);
if (current != null) {
return;
}
...
DiskLruCache.Editor editor = diskCache.edit(safeKey);
...
File file = editor.getFile(0);
if (writer.write(file)) {
editor.commit();
}
...
} finally {
writeLocker.release(safeKey);
}
}
...
//writer.write
public boolean write(@NonNull File file) {
return encoder.encode(data, file, options);
}
複製代碼
DiskLrcCache
具體的邏輯這裏先不介紹,只要知道了是經過key-value
緩存到了本地。後面能夠直接經過key獲取到緩存的數據。
接下來,咱們嘗試下,重啓App,讓Glide
從磁盤加載圖片。前面的步驟確定都是同樣的。咱們就直接從DecodeJob
的run
方法開始看。
public void run() {
...
runWrapped();
...
}
private void runWrapped() {
switch (runReason) {
case INITIALIZE:
stage = getNextStage(Stage.INITIALIZE);
currentGenerator = getNextGenerator();
runGenerators();
break;
...
}
}
private void runGenerators() {
...
while (!isCancelled && currentGenerator != null
&& !(isStarted = currentGenerator.startNext())) {
stage = getNextStage(stage);
currentGenerator = getNextGenerator();
if (stage == Stage.SOURCE) {
reschedule();
return;
}
}
...
}
複製代碼
以前是先在ResourceGenerator
,DataCacheGenerator
裏面去找裏面的loadData
能不能處理這個請求。 在第一次加載網絡圖片的時候,前面2個都不能處理。可是通過了前面的磁盤緩存後。咱們再進入DataCacheGenerator
來看下里面的邏輯。
public boolean startNext() {
while (modelLoaders == null || !hasNextModelLoader()) {
sourceIdIndex++;
if (sourceIdIndex >= cacheKeys.size()) {
return false;
}
Key sourceId = cacheKeys.get(sourceIdIndex);
Key originalKey = new DataCacheKey(sourceId, helper.getSignature());
cacheFile = helper.getDiskCache().get(originalKey);
if (cacheFile != null) {
this.sourceKey = sourceId;
modelLoaders = helper.getModelLoaders(cacheFile);
modelLoaderIndex = 0;
}
}
loadData = null;
boolean started = false;
while (!started && hasNextModelLoader()) {
ModelLoader<File, ?> modelLoader = modelLoaders.get(modelLoaderIndex++);
loadData =
modelLoader.buildLoadData(cacheFile, helper.getWidth(), helper.getHeight(),
helper.getOptions());
if (loadData != null && helper.hasLoadPath(loadData.fetcher.getDataClass())) {
started = true;
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
複製代碼
簡單的來說就是建立了一個DataCacheKey,而後helper.getDiskCache().get
獲取到緩存的數據。而後再交給對應的loadData
去處理。
這裏值得注意的是cacheKeys
,modelLoaders
咱們先來看cacheKeys
,一步步往上找 DataCacheGenerator->cacheKeys
=> DecodeHelper->cacheKeys
最終是這裏建立的,看下代碼
List<Key> getCacheKeys() {
...
List<LoadData<?>> loadData = getLoadData();
for (int i = 0, size = loadData.size(); i < size; i++) {
LoadData<?> data = loadData.get(i);
if (!cacheKeys.contains(data.sourceKey)) {
cacheKeys.add(data.sourceKey);
}
...
}
}
}
return cacheKeys;
}
複製代碼
cacheKeys
保存的實際上是LoadData
的sourceKey
. 這裏看下List<LoadData<?>>
是如何獲取到的
List<LoadData<?>> getLoadData() {
...
List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
for (int i = 0, size = modelLoaders.size(); i < size; i++) {
ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
LoadData<?> current =
modelLoader.buildLoadData(model, width, height, options);
if (current != null) {
loadData.add(current);
}
}
}
return loadData;
}
複製代碼
LoadData
其實ModelLoader. buildLoadData
生成的,因此,咱們就繼續往下看ModelLoader
是哪裏來的。
List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
//Registry.java
public <Model> List<ModelLoader<Model, ?>> getModelLoaders(@NonNull Model model) {
List<ModelLoader<Model, ?>> result = modelLoaderRegistry.getModelLoaders(model);
...
return result;
}
//ModelLoadRegistry.java
public <A> List<ModelLoader<A, ?>> getModelLoaders(@NonNull A model) {
List<ModelLoader<A, ?>> modelLoaders = getModelLoadersForClass(getClass(model));
...
}
//ModelLoadRegistry.java
private synchronized <A> List<ModelLoader<A, ?>> getModelLoadersForClass(
@NonNull Class<A> modelClass) {
List<ModelLoader<A, ?>> loaders = cache.get(modelClass);
if (loaders == null) {
loaders = Collections.unmodifiableList(multiModelLoaderFactory.build(modelClass));
cache.put(modelClass, loaders);
}
return loaders;
}
//MultiModelLoaderFactory.java
synchronized <Model> List<ModelLoader<Model, ?>> build(@NonNull Class<Model> modelClass) {
try {
List<ModelLoader<Model, ?>> loaders = new ArrayList<>();
for (Entry<?, ?> entry : entries) {
if (alreadyUsedEntries.contains(entry)) {
continue;
}
if (entry.handles(modelClass)) {
alreadyUsedEntries.add(entry);
loaders.add(this.<Model, Object>build(entry));
alreadyUsedEntries.remove(entry);
}
}
return loaders;
} catch (Throwable t) {
alreadyUsedEntries.clear();
throw t;
}
}
複製代碼
路徑很深,你們能夠直接看MultiModelLoaderFactory.build
方法. 值得注意的是這裏有個變量是entries
,咱們看看下是什麼東西。
private final List<Entry<?, ?>> entries = new ArrayList<>();
複製代碼
咱們使用ctrl+鼠標左鍵
找下引用的地方,看看哪裏往裏面添加東西了,添加了什麼東西。
private <Model, Data> void add( @NonNull Class<Model> modelClass, @NonNull Class<Data> dataClass, @NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory, boolean append) {
Entry<Model, Data> entry = new Entry<>(modelClass, dataClass, factory);
entries.add(append ? entries.size() : 0, entry);
}
複製代碼
再ctrl+鼠標左鍵
,看哪裏調用了add
,一步步往上找。
//MultiModelLoaderFactory.java
synchronized <Model, Data> void append( @NonNull Class<Model> modelClass, @NonNull Class<Data> dataClass, @NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory) {
add(modelClass, dataClass, factory, /*append=*/ true);
}
//ModelLoaderRegistry.java
public synchronized <Model, Data> void append( @NonNull Class<Model> modelClass, @NonNull Class<Data> dataClass, @NonNull ModelLoaderFactory<? extends Model, ? extends Data> factory) {
multiModelLoaderFactory.append(modelClass, dataClass, factory);
cache.clear();
}
//Registry.java
public <Model, Data> Registry append( @NonNull Class<Model> modelClass, @NonNull Class<Data> dataClass, @NonNull ModelLoaderFactory<Model, Data> factory) {
modelLoaderRegistry.append(modelClass, dataClass, factory);
return this;
}
複製代碼
最終找到,調用的地方是Glide
的構造方法。
因爲方法實在是太長了,這裏就直接貼出圖片。
咱們再來看下方法,注意下參數名。
public <Model, Data> Registry append(Class<Model> modelClass, Class<Data> dataClass, ModelLoaderFactory<Model, Data> factory) {
modelLoaderRegistry.append(modelClass, dataClass, factory);
return this;
}
複製代碼
modelClass->傳入的數據class,這裏咱們傳入的是http字符串,也就是String.class
dataClass->處理後獲得的數據class,前面文章介紹了第一次加載圖片獲得的實際上是InputStream
的子類
factory->建立處理傳入數據是modelClass這種類型,獲得數據是dataClass這種類型的處理器的工廠
咱們繼續回過頭看下
synchronized <Model> List<ModelLoader<Model, ?>> build(@NonNull Class<Model> modelClass) {
try {
List<ModelLoader<Model, ?>> loaders = new ArrayList<>();
for (Entry<?, ?> entry : entries) {
...
if (alreadyUsedEntries.contains(entry)) {
continue;
}
if (entry.handles(modelClass)) {
alreadyUsedEntries.add(entry);
loaders.add(this.<Model, Object>build(entry));
alreadyUsedEntries.remove(entry);
}
}
return loaders;
} catch (Throwable t) {
alreadyUsedEntries.clear();
throw t;
}
}
複製代碼
這裏就看起來清晰多了,先調用entry.handles(modelClass)
看看這個entry
能不能處理modelClass
這個類型的請求,若是能夠就調用build
方法構建一個ModelLoader
咱們一步步來,先看handles
方法
public boolean handles(@NonNull Class<?> modelClass) {
return this.modelClass.isAssignableFrom(modelClass);
}
複製代碼
很是簡單,就看modelClass是否是以前註冊的modelClass
的子類。
那麼繼續看build
方法。
private <Model, Data> ModelLoader<Model, Data> build(@NonNull Entry<?, ?> entry) {
return (ModelLoader<Model, Data>) Preconditions.checkNotNull(entry.factory.build(this));
}
複製代碼
其實就是調用entry.factory.build(this)
。前面已經介紹過了,factory其實就是前面註冊的第三個參數。那麼咱們就能夠看看以前,modelClass爲String的對應的幾個ModelLoaderFactory
根據前面的介紹是在Glide
構造函數中添加的。咱們就看下具體是哪幾個。
.append(String.class, InputStream.class, new DataUrlLoader.StreamFactory<String>())
.append(String.class, InputStream.class, new StringLoader.StreamFactory())
.append(String.class, ParcelFileDescriptor.class, new StringLoader.FileDescriptorFactory())
.append(String.class, AssetFileDescriptor.class, new StringLoader.AssetFileDescriptorFactory())
複製代碼
因此獲得的loaders
就是4個上面的factory
調用build
以後所建立的ModelLoader
。這裏就以StringLoader.StreamFactory.build
方法爲例子介紹下.
public ModelLoader<String, InputStream> build( @NonNull MultiModelLoaderFactory multiFactory) {
return new StringLoader<>(multiFactory.build(Uri.class, InputStream.class));
}
複製代碼
這裏就有個比較巧妙的地方,繼續調用了multiFactory
也就是MultiModelLoaderFactory
的build
方法,可是此次和前面不同,這裏傳了2個參數,Uri.class
對應modelClass
,InputStream
對應dataClass
,觸類旁通。前面已經介紹了傳了一個參數,就是找到前面註冊的modelClass爲String.class的factory
。這裏也是同樣,只不過這裏要找到modelClass爲Uri.classs,dataClass爲InputStream的factory
。而後使用factory構建出對應的ModelLoader
。
這裏咱們只須要知道,前面建立的StringLoader,內部有一個參數是uriLoader
,而這個uriLoader
就是處理modelClass爲Uri,dataClass爲InputStream的ModelLoader
。那麼咱們能夠在Glide
的構造方法內找一下對應的factory。
.append(Uri.class, InputStream.class, new DataUrlLoader.StreamFactory<Uri>())
.append(Uri.class, InputStream.class, new HttpUriLoader.Factory())
.append(Uri.class, InputStream.class, new AssetUriLoader.StreamFactory(context.getAssets()))
.append(Uri.class, InputStream.class, new MediaStoreImageThumbLoader.Factory(context))
.append(Uri.class, InputStream.class, new MediaStoreVideoThumbLoader.Factory(context))
.append(Uri.class,
InputStream.class,
new UriLoader.StreamFactory(contentResolver))
...
複製代碼
有點多,我就不一一寫出了。
接下來就往前面看。
//ModelLoaderRegistry.java
public <A> List<ModelLoader<A, ?>> getModelLoaders(@NonNull A model) {
//這裏獲取到了4個
List<ModelLoader<A, ?>> modelLoaders = getModelLoadersForClass(getClass(model));
int size = modelLoaders.size();
boolean isEmpty = true;
List<ModelLoader<A, ?>> filteredLoaders = Collections.emptyList();
for (int i = 0; i < size; i++) {
ModelLoader<A, ?> loader = modelLoaders.get(i);
//這裏過濾掉了一個
if (loader.handles(model)) {
if (isEmpty) {
filteredLoaders = new ArrayList<>(size - i);
isEmpty = false;
}
filteredLoaders.add(loader);
}
}
return filteredLoaders;
}
複製代碼
你們能夠注意下上面的註釋,就是loader.handlers
過濾了一個ModelLoader
,這裏就直接說了,過濾了DataUrlLoader
public boolean handles(@NonNull Model model) {
return model.toString().startsWith(DATA_SCHEME_IMAGE);
}
複製代碼
顯然咱們傳入的字符串不是以這個爲開頭,因此爲false。 因此最後傳回去的是3個ModelLoader。繼續往前看。
List<LoadData<?>> getLoadData() {
if (!isLoadDataSet) {
isLoadDataSet = true;
loadData.clear();
//這邊就是前面獲得的3個ModelLoader
List<ModelLoader<Object, ?>> modelLoaders = glideContext.getRegistry().getModelLoaders(model);
for (int i = 0, size = modelLoaders.size(); i < size; i++) {
ModelLoader<Object, ?> modelLoader = modelLoaders.get(i);
LoadData<?> current =
modelLoader.buildLoadData(model, width, height, options);
if (current != null) {
loadData.add(current);
}
}
}
return loadData;
}
複製代碼
前面其實已經介紹過了,返回的實際上是3個StringLoader
,只不過是裏面的uriLoader
不太同樣罷了。
public LoadData<Data> buildLoadData(@NonNull String model, int width, int height, @NonNull Options options) {
Uri uri = parseUri(model);
if (uri == null || !uriLoader.handles(uri)) {
return null;
}
return uriLoader.buildLoadData(uri, width, height, options);
}
...
//MultiModelLoader.java
public boolean handles(@NonNull Model model) {
for (ModelLoader<Model, Data> modelLoader : modelLoaders) {
if (modelLoader.handles(model)) {
return true;
}
}
return false;
}
複製代碼
uriLoader
是一個MultiModelLoader
,其實也是遍歷一下,看看MultiModelLoader
內部的ModelLoader
能不能處理。
//HttpUriLoader
private static final Set<String> SCHEMES =
Collections.unmodifiableSet(new HashSet<>(Arrays.asList("http", "https")));
public boolean handles(@NonNull Uri model) {
return SCHEMES.contains(model.getScheme());
}
複製代碼
找到HttpUriLoader
可以處理。而後調用HttpUriLoader.buildLoaderData
public LoadData<InputStream> buildLoadData(@NonNull Uri model, int width, int height, @NonNull Options options) {
return urlLoader.buildLoadData(new GlideUrl(model.toString()), width, height, options);
}
複製代碼
這裏很奇怪,這裏又來了一個urlLoader
是什麼東西。 建立HttpUriLoader
的時候是根據一個factory
建立的,
public static class Factory implements ModelLoaderFactory<Uri, InputStream> {
...
public ModelLoader<Uri, InputStream> build(MultiModelLoaderFactory multiFactory) {
return new HttpUriLoader(multiFactory.build(GlideUrl.class, InputStream.class));
}
...
}
複製代碼
這段代碼感受又很是熟悉,跟前面很像,只不過這裏的modelClass
是GlideUrl
,dataClass
是InputStream
,咱們在Glide
構造方法裏面找一下
.append(GlideUrl.class, InputStream.class, new HttpGlideUrlLoader.Factory())
複製代碼
就這一個。 因此剛纔urlLoader
其實就是由HttpGlideUrlLoader.Factory()
構建的HttpGlideUrlLoader
。那麼咱們來看下HttpGlideUrlLoader.buildLoadData
public LoadData<InputStream> buildLoadData(@NonNull GlideUrl model, int width, int height, @NonNull Options options) {
GlideUrl url = model;
...
return new LoadData<>(url, new HttpUrlFetcher(url, timeout));
}
複製代碼
HttpUrlFetcher
其實就是真正發起http
請求獲取數據的fetcher
。這裏就不在深刻了。
這裏咱們從新再看下這行代碼
urlLoader.buildLoadData(new GlideUrl(model.toString()), width, height, options)
複製代碼
咱們能夠看下GlideUrl
public class GlideUrl implements Key 複製代碼
它實現了Key
接口。因此前面獲取DiskCacheKey
傳入的參數其實就是GlideUrl
。那麼咱們就從新再回到最前面。DataCacheGenerator
public boolean startNext() {
while (modelLoaders == null || !hasNextModelLoader()) {
...
Key sourceId = cacheKeys.get(sourceIdIndex);
...
Key originalKey = new DataCacheKey(sourceId, helper.getSignature());
cacheFile = helper.getDiskCache().get(originalKey);
if (cacheFile != null) {
this.sourceKey = sourceId;
modelLoaders = helper.getModelLoaders(cacheFile);
modelLoaderIndex = 0;
}
}
loadData = null;
boolean started = false;
while (!started && hasNextModelLoader()) {
ModelLoader<File, ?> modelLoader = modelLoaders.get(modelLoaderIndex++);
loadData =
modelLoader.buildLoadData(cacheFile, helper.getWidth(), helper.getHeight(),
helper.getOptions());
if (loadData != null && helper.hasLoadPath(loadData.fetcher.getDataClass())) {
started = true;
loadData.fetcher.loadData(helper.getPriority(), this);
}
}
return started;
}
複製代碼
通過前面介紹如何獲取到ModelLoader
已經Key
是什麼以後,再來看下這段代碼,就會發現有不太同樣的認識。
cacheFile
這裏已經不爲null。 而後繼續往下,從helper.getModelLoaders(cacheFile),其實就是找到modelClass
爲 File
的factory
。
.append(File.class, ByteBuffer.class, new ByteBufferFileLoader.Factory())
.append(File.class, InputStream.class, new FileLoader.StreamFactory())
.append(File.class, File.class, new FileDecoder())
.append(File.class, ParcelFileDescriptor.class, new FileLoader.FileDescriptorFactory())
.append(File.class, File.class, UnitModelLoader.Factory.<File>getInstance())
複製代碼
而後反正就根據我剛纔那樣一步步往下走就行了,就會找到對應的ModelLoader
而後生成對應的LoadData
,這裏就直接再也不跟入了, 這裏LoadData
實際上是ByteBufferFileLoader
private static final class ByteBufferFetcher implements DataFetcher<ByteBuffer> {
...
@Override
public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super ByteBuffer> callback) {
ByteBuffer result;
...
result = ByteBufferUtil.fromFile(file);
...
callback.onDataReady(result);
}
複製代碼
裏面的fetcher
就是ByteBufferFetcher
,而後調用loadData
方法讀取到數據。
這篇文章主要是對磁盤緩存數據還有獲取數據的分析,以及ModelLoader
的分析。後續還會繼續深刻分析Glide