Glide源碼(一)

Picasso,Glide坪蚁,F(xiàn)resco對比

上一篇我們分析了Picasso啃擦,這一篇我們來分析Glide源碼的調(diào)用流程馍惹,目前主流的圖片加載框架除了Picasso和Glide脯厨,還有Facebook開源的Fresco,有時間也將開一篇來分析。下面用一張表格來對3者進行對比,如下:


image.png

示例

 Glide.with( activity )
      .load( imageUrl )//指定加載路徑
      .placeholder( R.mipmap.ic_launcher )//加載前默認圖
      .error( R.mipmap.ic_launcher )//加載錯誤時顯示的圖片
      .override( 300, 300 )//指定圖片大小
      .centerCrop()//縮放叠聋,太大會裁剪并填滿整個控件
      .fitCenter()//縮放,會顯示完整圖片受裹,但有可能不會填滿整個控件
      .skipMemoryCache( true )//跳過內(nèi)緩存碌补,但仍會使用硬盤緩存
      .diskCacheStrategy( DiskCacheStrategy.NONE )//不進行磁盤緩存
      .diskCacheStrategy( DiskCacheStrategy.RESOURCE )//只緩存轉(zhuǎn)換過后的圖片
      .diskCacheStrategy( DiskCacheStrategy.ALL )//既緩存原始圖片,也緩存轉(zhuǎn)換過后的圖片
      .diskCacheStrategy( DiskCacheStrategy.DATA )//只緩存原始圖片
      .diskCacheStrategy( DiskCacheStrategy.AUTOMATIC )//根據(jù)圖片資源自動選擇一種緩存策略(默認選項)
      .priority( Priority.HIGH )//指定優(yōu)先級,但沒法保證一定按優(yōu)先級加載
      .into( (ImageView) view );//顯示目標

如示例所示厦章,根據(jù)不同的需求場景镇匀,我們可以為Glide指定不同的配置。由于Glide源碼非常龐大和復(fù)雜闷袒,因此,本篇只分析3個主要的調(diào)用流程岩梳,即:

  Glide.with( getApplicationContext() )
          .load( imageUrl )
          .into( (ImageView) view );

源碼分析

public class Glide implements ComponentCallbacks2 {
  ......
  public static RequestManager with(@NonNull Context context) {
    return getRetriever(context).get(context);
  }

  
  public static RequestManager with(@NonNull Activity activity) {
    return getRetriever(activity).get(activity);
  }


public static RequestManager with(@NonNull FragmentActivity activity) {
    return getRetriever(activity).get(activity);
  }


 public static RequestManager with(@NonNull Fragment fragment) {
    return getRetriever(fragment.getActivity()).get(fragment);
  }

public static RequestManager with(@NonNull View view) {
    return getRetriever(view.getContext()).get(view);
  }

    ......

//獲取RequestManagerRetriever 
 private static RequestManagerRetriever getRetriever(@Nullable Context context) {
    Preconditions.checkNotNull(
        context,
        "You cannot start a load on a not yet attached View or a Fragment where getActivity() "
            + "returns null (which usually occurs when getActivity() is called before the Fragment "
            + "is attached or after the Fragment is destroyed).");
    //初始化Glide囊骤,并獲取RequestManagerRetriever 
    return Glide.get(context).getRequestManagerRetriever();
  }
}

with根據(jù)不同的上下文參數(shù),提供了多個重載方法冀值,因為不同的上下文環(huán)境對圖片加載的生命周期也物,會有不同的影響。

with方法將返回一個RequestManager 列疗,而RequestManager 的獲取滑蚯,需要通過RequestManagerRetriever()這個檢索器來構(gòu)造,并且抵栈,一個上下文環(huán)境只持有一個檢索器告材。

假設(shè)第一次調(diào)用,在獲取RequestManagerRetriever檢索器前古劲,將先初始化Glide斥赋。如源碼中所示,Glide.get(context)將初始化并返回Glide對象产艾。

public class Glide implements ComponentCallbacks2 {

    //獲取單例
  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;
  }

  //構(gòu)造一個new GlideBuilder()并調(diào)用雙參的重載方法
  private static void initializeGlide(@NonNull Context context) {
    initializeGlide(context, new GlideBuilder());
  }

  //初始化
  private static void initializeGlide(@NonNull Context context, @NonNull GlideBuilder builder) {
    Context applicationContext = context.getApplicationContext();
          ......
    //構(gòu)造Glide對象
    Glide glide = builder.build(applicationContext);
          ......
    //保存到靜態(tài)成員中
    Glide.glide = glide;
  }

    .......
}

Glide通過雙重檢查鎖方式疤剑,來初始化和構(gòu)造單例對象。我們看到,在initializeGlide方法中new了一個GlideBuilder闷堡,它用來構(gòu)建Glide對象隘膘,并將對象保存到靜態(tài)成員變量glide 中。我們看build方法如何構(gòu)建杠览。

public final class GlideBuilder {

    ......

  Glide build(@NonNull Context context) {
    // 創(chuàng)建資源加載請求器弯菊,是一個線程池,用于加載源數(shù)據(jù)(URL等)
    if (sourceExecutor == null) {
      sourceExecutor = GlideExecutor.newSourceExecutor();
    }
  //查找磁盤緩存的線程池
    if (diskCacheExecutor == null) {
      diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();
    }
    //動畫執(zhí)行的線程池
    if (animationExecutor == null) {
      animationExecutor = GlideExecutor.newAnimationExecutor();
    }
  // 內(nèi)存計算器
    if (memorySizeCalculator == null) {
      memorySizeCalculator = new MemorySizeCalculator.Builder(context).build();
    }
   // 網(wǎng)絡(luò)狀態(tài)檢測器
    if (connectivityMonitorFactory == null) {
      connectivityMonitorFactory = new DefaultConnectivityMonitorFactory();
    }

  //Bitmap復(fù)用池
    if (bitmapPool == null) {
      int size = memorySizeCalculator.getBitmapPoolSize();
      if (size > 0) {
        bitmapPool = new LruBitmapPool(size);
      } else {
        bitmapPool = new BitmapPoolAdapter();
      }
    }

   // 數(shù)組資源緩存池
    if (arrayPool == null) {
      arrayPool = new LruArrayPool(memorySizeCalculator.getArrayPoolSizeInBytes());
    }

    //用于緩存加載完成和顯示的圖片數(shù)據(jù)資源
    if (memoryCache == null) {
      memoryCache = new LruResourceCache(memorySizeCalculator.getMemoryCacheSize());
    }
   // 磁盤緩存器踱阿,默認為 APP 內(nèi)部私密目錄
    if (diskCacheFactory == null) {
      diskCacheFactory = new InternalCacheDiskCacheFactory(context);
    }
  
  // 圖片加載引擎误续,用于執(zhí)行圖片加載請求驅(qū)動
    if (engine == null) {
      engine =
          new Engine(
              memoryCache,
              diskCacheFactory,
              diskCacheExecutor,
              sourceExecutor,
              GlideExecutor.newUnlimitedSourceExecutor(),
              GlideExecutor.newAnimationExecutor(),
              isActiveResourceRetentionAllowed);
    }

// 構(gòu)建一個請求監(jiān)聽器列表
    if (defaultRequestListeners == null) {
      defaultRequestListeners = Collections.emptyList();
    } else {
      defaultRequestListeners = Collections.unmodifiableList(defaultRequestListeners);
    }

  //構(gòu)建RequestManager的檢索器
    RequestManagerRetriever requestManagerRetriever =
        new RequestManagerRetriever(requestManagerFactory);

  //構(gòu)建Glide
    return new Glide(
        context,
        engine,
        memoryCache,
        bitmapPool,
        arrayPool,
        requestManagerRetriever,
        connectivityMonitorFactory,
        logLevel,
        defaultRequestOptions.lock(),
        defaultTransitionOptions,
        defaultRequestListeners,
        isLoggingRequestOriginsEnabled);
  }

buid方法構(gòu)建了許多池子,同時生成上面RequestManager的檢索器扫茅,在最后構(gòu)建Glide時將所有參數(shù)傳入蹋嵌。 Glide 的構(gòu)造方法代碼量非常多,故省略大量代碼葫隙,只顯示核心邏輯栽烂。

Glide(
    @NonNull Context context,
    @NonNull Engine engine,
    @NonNull MemoryCache memoryCache,
    @NonNull BitmapPool bitmapPool,
    @NonNull ArrayPool arrayPool,
    @NonNull RequestManagerRetriever requestManagerRetriever,
    @NonNull ConnectivityMonitorFactory connectivityMonitorFactory,
    int logLevel,
    @NonNull RequestOptionsFactory defaultRequestOptionsFactory,
    @NonNull Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions,
    @NonNull List<RequestListener<Object>> defaultRequestListeners,
    boolean isLoggingRequestOriginsEnabled,
    boolean isImageDecoderEnabledForBitmaps,
    int hardwareBitmapFdLimit) {

    // 賦值
  this.engine = engine;
  this.bitmapPool = bitmapPool;
  this.arrayPool = arrayPool;
  this.memoryCache = memoryCache;
  this.requestManagerRetriever = requestManagerRetriever;
  this.connectivityMonitorFactory = connectivityMonitorFactory;
  this.defaultRequestOptionsFactory = defaultRequestOptionsFactory;

  final Resources resources = context.getResources();

  // 新建注冊器
  registry = new Registry();
  registry.register(new DefaultImageHeaderParser());
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
    registry.register(new ExifInterfaceImageHeaderParser());
  }

  List<ImageHeaderParser> imageHeaderParsers = registry.getImageHeaderParsers();

  // 創(chuàng)建解碼器
  ByteBufferGifDecoder byteBufferGifDecoder =
      new ByteBufferGifDecoder(context, imageHeaderParsers, bitmapPool, arrayPool);
  ResourceDecoder<ParcelFileDescriptor, Bitmap> parcelFileDescriptorVideoDecoder =
      VideoDecoder.parcel(bitmapPool);

  ResourceDecoder<ByteBuffer, Bitmap> byteBufferBitmapDecoder;
  ResourceDecoder<InputStream, Bitmap> streamBitmapDecoder;
  if (isImageDecoderEnabledForBitmaps && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    streamBitmapDecoder = new InputStreamBitmapImageDecoderResourceDecoder();
    byteBufferBitmapDecoder = new ByteBufferBitmapImageDecoderResourceDecoder();
  } else {
    Downsampler downsampler =
        new Downsampler(
            registry.getImageHeaderParsers(),
            resources.getDisplayMetrics(),
            bitmapPool,
            arrayPool);
    byteBufferBitmapDecoder = new ByteBufferBitmapDecoder(downsampler);
    streamBitmapDecoder = new StreamBitmapDecoder(downsampler, arrayPool);
  }

  ResourceDrawableDecoder resourceDrawableDecoder = new ResourceDrawableDecoder(context);
  // 創(chuàng)建數(shù)據(jù)轉(zhuǎn)換器
  ResourceLoader.StreamFactory resourceLoaderStreamFactory =
      new ResourceLoader.StreamFactory(resources);
  ResourceLoader.UriFactory resourceLoaderUriFactory = new ResourceLoader.UriFactory(resources);
  ResourceLoader.FileDescriptorFactory resourceLoaderFileDescriptorFactory =
      new ResourceLoader.FileDescriptorFactory(resources);
  ResourceLoader.AssetFileDescriptorFactory resourceLoaderAssetFileDescriptorFactory =
      new ResourceLoader.AssetFileDescriptorFactory(resources);
  BitmapEncoder bitmapEncoder = new BitmapEncoder(arrayPool);

  // 創(chuàng)建轉(zhuǎn)碼器
  BitmapBytesTranscoder bitmapBytesTranscoder = new BitmapBytesTranscoder();
  GifDrawableBytesTranscoder gifDrawableBytesTranscoder = new GifDrawableBytesTranscoder();

  ContentResolver contentResolver = context.getContentResolver();

  // 注冊各個類型的解碼器和編碼器
  registry
      .append(ByteBuffer.class, new ByteBufferEncoder())
      .append(InputStream.class, new StreamEncoder(arrayPool))

      ......

      .register(
          Drawable.class,
          byte[].class,
          new DrawableBytesTranscoder(
              bitmapPool, bitmapBytesTranscoder, gifDrawableBytesTranscoder))
      .register(GifDrawable.class, byte[].class, gifDrawableBytesTranscoder);

  // 創(chuàng)建圖片顯示目標對象工廠
  ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();
  // 創(chuàng)建 GlideContext 對象,注意傳入的參數(shù)
  glideContext =
      new GlideContext(
          context,
          arrayPool,
          registry,
          imageViewTargetFactory,
          defaultRequestOptionsFactory,
          defaultTransitionOptions,
          defaultRequestListeners,
          engine,
          isLoggingRequestOriginsEnabled,
          logLevel);
}

構(gòu)造方法主要是初始化模型轉(zhuǎn)換器、解碼器腺办、轉(zhuǎn)碼器和編碼器焰手,并對各種類型在注冊表進行注冊。Glide的整個加載流程將經(jīng)歷:model(數(shù)據(jù)源)-->data(轉(zhuǎn)換數(shù)據(jù))-->decode(解碼)-->transformed(縮放)-->transcoded(轉(zhuǎn)碼)-->encoded(編碼保存到本地)怀喉,所以在構(gòu)造方法里初始化這些對象书妻,是為Gilde后續(xù)的加載流程做準備的。

回到一開始的width方法躬拢。在GlideBuilder 中躲履,已經(jīng)創(chuàng)建好了RequestManagerRetriever檢索器 ,RequestManagerRetriever 將通過get方法來獲取RequestManager聊闯。

public class RequestManagerRetriever implements Handler.Callback {

      ......
  private volatile RequestManager applicationManager;
  public RequestManagerRetriever(@Nullable RequestManagerFactory factory) {
    this.factory = factory != null ? factory : DEFAULT_FACTORY;
    handler = new Handler(Looper.getMainLooper(), this /* Callback */);
  }
      ......
  //Application上下文環(huán)境
  private RequestManager getApplicationManager(@NonNull Context context) {
     if (applicationManager == null) {
      synchronized (this) {
        if (applicationManager == null) {
         Glide glide = Glide.get(context.getApplicationContext());
          //新建ApplicationLifecycle()和EmptyRequestManagerTreeNode
          applicationManager =
              factory.build(
                  glide,
                  new ApplicationLifecycle(),
                  new EmptyRequestManagerTreeNode(),
                  context.getApplicationContext());
        }
      }
    }
    return applicationManager;
  }

//獲取RequestManager 
  public RequestManager get(@NonNull Context context) {
    if (context == null) {
      throw new IllegalArgumentException("You cannot start a load on a null Context");
    //在主線程中工猜,并且上下文不是Application
    } else if (Util.isOnMainThread() && !(context instanceof Application)) {
      //對3種上下文進行判斷
      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 interface RequestManagerFactory {
    @NonNull
    RequestManager build(
        @NonNull Glide glide,
        @NonNull Lifecycle lifecycle,
        @NonNull RequestManagerTreeNode requestManagerTreeNode,
        @NonNull Context context);
  }


private static final RequestManagerFactory DEFAULT_FACTORY = new RequestManagerFactory() {
    @NonNull
    @Override
    public RequestManager build(@NonNull Glide glide, @NonNull Lifecycle lifecycle,
        @NonNull RequestManagerTreeNode requestManagerTreeNode, @NonNull Context context) {
      return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
    }
  };
}

在構(gòu)造RequestManagerRetriever時,倘若沒有設(shè)置RequestManagerFactory工廠菱蔬,那么將使用默認的匿名內(nèi)部類DEFAULT_FACTORY 來構(gòu)造RequestManager篷帅。

RequestManagerRetriever的get方法主要分2種情況,其中子線程和Application上下文環(huán)境最為簡單拴泌,它將使用Application為上下文魏身,構(gòu)建RequestManager,并且由源碼所示蚪腐,RequestManager也是一個單例叠骑,也就是說,一種上下文只有一個RequestManagerRetriever檢索器削茁,也只有一個RequestManager對象宙枷。

而其他上下文情況,最終都會以Activity為上下文茧跋,調(diào)用參數(shù)為Activity的get方法慰丛,我們繼續(xù)分析,看以Activity為上下文的調(diào)用過程和以Application為上下文的情況有什么不同瘾杭。


public class RequestManagerRetriever implements Handler.Callback {
  //Tag緩存
   static final String FRAGMENT_TAG = "com.bumptech.glide.manager";
  //map緩存
    final Map<android.app.FragmentManager, RequestManagerFragment> pendingRequestManagerFragments =
      new HashMap<>();
    ......

  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,  null, isActivityVisible(activity));
    }
  }

  //activity是否退出了
  private static boolean isActivityVisible(Activity activity) {
       return !activity.isFinishing();
  }


  private RequestManager fragmentGet(@NonNull Context context,
      @NonNull android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint,
      boolean isParentVisible) {
    //獲取一個空fragment
    RequestManagerFragment current = getRequestManagerFragment(fm, parentHint, isParentVisible);
    //獲取RequestManager 
    RequestManager requestManager = current.getRequestManager();
    //為空則構(gòu)建
    if (requestManager == null) {
       Glide glide = Glide.get(context);
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }

  private RequestManagerFragment getRequestManagerFragment(
      @NonNull final android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint,
      boolean isParentVisible) {
    //通過名為FRAGMENT_TAG的Tag獲取
    RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    //空則從緩存中獲取
    if (current == null) {
      current = pendingRequestManagerFragments.get(fm);
      //緩存空則新建
      if (current == null) {
        current = new RequestManagerFragment();
        current.setParentFragmentHint(parentHint);
        //Activity沒退出
        if (isParentVisible) {
          //開啟生命周期監(jiān)聽
          current.getGlideLifecycle().onStart();
        }
        //緩存起來
        pendingRequestManagerFragments.put(fm, current);
        //加到當前Activity
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
        //發(fā)送ID_REMOVE_FRAGMENT_MANAGER消息清除緩存
        handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
      }
    }
    return current;
  }

  //消息回調(diào)移除緩存RequestManagerFragment 
  @Override
  public boolean handleMessage(Message message) {
    boolean handled = true;
    Object removed = null;
    Object key = null;
    switch (message.what) {
      case ID_REMOVE_FRAGMENT_MANAGER:
        android.app.FragmentManager fm = (android.app.FragmentManager) message.obj;
        key = fm;
        //從緩存移除
        removed = pendingRequestManagerFragments.remove(fm);
        break;
      case ID_REMOVE_SUPPORT_FRAGMENT_MANAGER:
        FragmentManager supportFm = (FragmentManager) message.obj;
        key = supportFm;
        removed = pendingSupportRequestManagerFragments.remove(supportFm);
        break;
      default:
        handled = false;
        break;
    }
    if (handled && removed == null && Log.isLoggable(TAG, Log.WARN)) {
      Log.w(TAG, "Failed to remove expected request manager fragment, manager: " + key);
    }
    return handled;
  }


}

RequestManagerFragment 是一個空的Fragment诅病,Glide正是通過它來監(jiān)聽Activity的生命周期,換句話說粥烁,當Activity的生命周期方法被回調(diào)贤笆,也就同時回調(diào)了Fragment(RequestManagerFragment )。

如源碼中所示讨阻,如果RequestManagerFragment被添加到當前的Activity中芥永,那么通過變量名FRAGMENT_TAG就可以獲取到,那為什么還需要使用pendingSupportRequestManagerFragments這個Map來進行緩存钝吮,而添加到Activity后埋涧,又立即通過消息將其從Map中移除板辽?

因為并發(fā)。以下面的代碼為例:

Glide.with(activity).load(url1).into(imageView1); //request1
Glide.with(activity).load(url2).into(imageView2); //request2

Fragment添加是通過Handler消息隊列操作的棘催,而消息隊列執(zhí)行在主線程之后劲弦。假設(shè)request1創(chuàng)建RequestManagerFragment,并提交了事務(wù)醇坝,在RequestManagerFragment添加消息未執(zhí)行邑跪,也就是說RequestManagerFragment未被添加到Acitivy中前,request2執(zhí)行到fm.findFragmentByTag(FRAGMENT_TAG)呼猪,current 將會為null画畅,那么,如果不使用map來緩存郑叠,RequestManagerFragment又將實例化一個夜赵,也就意味著明棍,當前Activity將出現(xiàn)重復(fù)添加RequestManagerFragment的情況乡革。

由于移除消息在提交事務(wù)消息之后,等到移除消息執(zhí)行時摊腋,后面的請求已經(jīng)能通過FRAGMENT_TAG獲取到RequestManagerFragment了沸版,Map沒有必要再繼續(xù)緩存著,因此兴蒸,從緩存移除视粮,以避免內(nèi)存泄漏和減少內(nèi)存壓力。

下面來看RequestManagerFragment是監(jiān)聽Activity生命周期做了哪些操作橙凳。

public class RequestManagerFragment extends Fragment {

  private final ActivityFragmentLifecycle lifecycle;

  public RequestManagerFragment() {
    this(new ActivityFragmentLifecycle());
  }

  RequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
    this.lifecycle = lifecycle;
  }

public void onDetach() {
    super.onDetach();
    unregisterFragmentWithRoot();
  }


 @Override
  public void onStart() {
    super.onStart();
    lifecycle.onStart();
  }

  @Override
  public void onStop() {
    super.onStop();
    lifecycle.onStop();
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    lifecycle.onDestroy();
    unregisterFragmentWithRoot();
  }

}

RequestManagerFragment 構(gòu)造時構(gòu)建了一個ActivityFragmentLifecycle 對象蕾殴,它正是負責(zé)生命周期的回調(diào)。

class ActivityFragmentLifecycle implements Lifecycle {
   private final Set<LifecycleListener> lifecycleListeners =
      Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>());
  private boolean isStarted;
  private boolean isDestroyed;

  @Override
  public void addListener(@NonNull LifecycleListener listener) {
    lifecycleListeners.add(listener);

    if (isDestroyed) {
      listener.onDestroy();
    } else if (isStarted) {
      listener.onStart();
    } else {
      listener.onStop();
    }
  }

  @Override
  public void removeListener(@NonNull LifecycleListener listener) {
    lifecycleListeners.remove(listener);
  }

  void onStart() {
    isStarted = true;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onStart();
    }
  }

  void onStop() {
    isStarted = false;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onStop();
    }
  }

  void onDestroy() {
    isDestroyed = true;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
      lifecycleListener.onDestroy();
    }
  }
}
public interface Lifecycle {

  void addListener(@NonNull LifecycleListener listener);

  void removeListener(@NonNull LifecycleListener listener);
}

ActivityFragmentLifecycle 實現(xiàn)了Lifecycle 接口岛啸,通過addListener方法將LifecycleListener添加到集合中钓觉,當Activity生命周期被回調(diào),將觸發(fā)RequestManagerFragment對應(yīng)的生命周期坚踩,也將觸發(fā)ActivityFragmentLifecycle 遍歷lifecycleListeners集合荡灾,回調(diào)每個LifecycleListener對應(yīng)的方法。

public interface LifecycleListener {

  void onStart();

  void onStop();

  void onDestroy();
}

LifecycleListener接口定義了3個生命周期回調(diào)瞬铸,它的LifecycleListener的實現(xiàn)類有許多個批幌,其中就包括RequestManager類。

with方法分析完畢嗓节,總結(jié)一下它所做的工作:

  • 構(gòu)造并初始化Gilde對象荧缘;
  • 在構(gòu)建Gilde對象的過程中,構(gòu)建RequestManagerRetriever檢索器拦宣;
  • 檢索器在上下文環(huán)境不是Application的情況下胜宇,會構(gòu)建一個RequestManagerFragment 來監(jiān)聽頁面的生命周期耀怜。
  • 構(gòu)建RequestManager對象。Application環(huán)境下桐愉,RequestManagerRetriever持有RequestManager财破,非Application環(huán)境下,RequestManagerFragment持有RequestManager从诲。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末左痢,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子系洛,更是在濱河造成了極大的恐慌俊性,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件描扯,死亡現(xiàn)場離奇詭異定页,居然都是意外死亡,警方通過查閱死者的電腦和手機绽诚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門典徊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人恩够,你說我怎么就攤上這事卒落。” “怎么了蜂桶?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵儡毕,是天一觀的道長。 經(jīng)常有香客問我扑媚,道長腰湾,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任疆股,我火速辦了婚禮费坊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘押桃。我一直安慰自己葵萎,他們只是感情好,可當我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布唱凯。 她就那樣靜靜地躺著羡忘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪磕昼。 梳的紋絲不亂的頭發(fā)上卷雕,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天,我揣著相機與錄音票从,去河邊找鬼漫雕。 笑死滨嘱,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的浸间。 我是一名探鬼主播太雨,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼魁蒜!你這毒婦竟也來了囊扳?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤兜看,失蹤者是張志新(化名)和其女友劉穎锥咸,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體细移,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡搏予,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了弧轧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片雪侥。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖劣针,靈堂內(nèi)的尸體忽然破棺而出校镐,到底是詐尸還是另有隱情亿扁,我是刑警寧澤捺典,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站从祝,受9級特大地震影響襟己,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜牍陌,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一擎浴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧毒涧,春花似錦贮预、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至捡偏,卻和暖如春唤冈,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背银伟。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工你虹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留绘搞,地道東北人。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓傅物,卻偏偏與公主長得像夯辖,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子董饰,可洞房花燭夜當晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內(nèi)容