美文网首页Android源码分析
【源码阅读】Glide源码阅读之with方法(一)

【源码阅读】Glide源码阅读之with方法(一)

作者: 欢子3824 | 来源:发表于2018-12-05 17:09 被阅读29次

    前言:本篇基于4.8.0版本
    【源码阅读】Glide源码阅读之with方法(一)
    【源码阅读】Glide源码阅读之load方法(二)
    【源码阅读】Glide源码阅读之into方法(三)
    大多数情况下,我们使用glide 就一句代码

    Glide.with(context).load(url).into(imageView);

    但是这一句代码里面蕴含着成吨的代码!

    with方法有以下几个重载方法

     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 android.app.Fragment fragment) {
        return getRetriever(fragment.getActivity()).get(fragment);
      }
      public static RequestManager with(@NonNull View view) {
        return getRetriever(view.getContext()).get(view);
      }
    

    其中,getRetriever返回的是个RequestManagerRetriever对象

    private static RequestManagerRetriever getRetriever(@Nullable Context context) {
        // Context could be null for other reasons (ie the user passes in null), but in practice it will
        // only occur due to errors with the Fragment lifecycle.
        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).");
        return Glide.get(context).getRequestManagerRetriever();
      }
    

    接着是RequestManagerRetriever.get方法,在传入Context 、Activity 、FragmentActivity 、Fragment 、 android.app.Fragment、View 几种情况略有不同,大致可以分为Application和非Application

    • Application 它生命周期即应用程序的生命周期,如果应用程序关闭的话,Glide的加载也会同时终止。
      @NonNull
      private RequestManager getApplicationManager(@NonNull Context context) {
        // Either an application context or we're on a background thread.
        if (applicationManager == null) {
          synchronized (this) {
            if (applicationManager == null) {
              // Normally pause/resume is taken care of by the fragment we add to the fragment or
              // activity. However, in this case since the manager attached to the application will not
              // receive lifecycle events, we must force the manager to start resumed using
              // ApplicationLifecycle.
    
              // TODO(b/27524013): Factor out this Glide.get() call.
              Glide glide = Glide.get(context.getApplicationContext());
              applicationManager =
                  factory.build(
                      glide,
                      new ApplicationLifecycle(),
                      new EmptyRequestManagerTreeNode(),
                      context.getApplicationContext());
            }
          }
        }
    
        return applicationManager;
      }
    
    • 非Application 都是向当前Activity添加一个隐藏的Fragment,当Activity销毁时,该Fragment也会销毁,销毁时,Glide 就会取消本次加载。
     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)) {
          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);
      }
    

    唯一有区别的是,FragmentActivity和Fragment使用的是SupportRequestManagerFragment,Activity使用的是RequestManagerFragment;SupportRequestManagerFragment继承的是v4包的,而RequestManagerFragment是继承android.app.Fragment。

     @NonNull
      private SupportRequestManagerFragment getSupportRequestManagerFragment(
          @NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
        SupportRequestManagerFragment current =
            (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
        if (current == null) {
          current = pendingSupportRequestManagerFragments.get(fm);
          if (current == null) {
            current = new SupportRequestManagerFragment();
            current.setParentFragmentHint(parentHint);
            if (isParentVisible) {
              current.getGlideLifecycle().onStart();
            }
            pendingSupportRequestManagerFragments.put(fm, current);
            fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
            handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
          }
        }
        return current;
      }
    
    
      @NonNull
      private RequestManagerFragment getRequestManagerFragment(
          @NonNull final android.app.FragmentManager fm,
          @Nullable android.app.Fragment parentHint,
          boolean isParentVisible) {
        RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
        if (current == null) {
          current = pendingRequestManagerFragments.get(fm);
          if (current == null) {
            current = new RequestManagerFragment();
            current.setParentFragmentHint(parentHint);
            if (isParentVisible) {
              current.getGlideLifecycle().onStart();
            }
            pendingRequestManagerFragments.put(fm, current);
            fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
            handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
          }
        }
        return current;
      }
    

    SupportRequestManagerFragment中部分代码

     @Override
      public void onAttach(Context context) {
        super.onAttach(context);
        try {
          registerFragmentWithRoot(getActivity());
        } catch (IllegalStateException e) {
          // OnAttach can be called after the activity is destroyed, see #497.
          if (Log.isLoggable(TAG, Log.WARN)) {
            Log.w(TAG, "Unable to register fragment with root", e);
          }
        }
      }
    
      @Override
      public void onDetach() {
        super.onDetach();
        parentFragmentHint = null;
        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();
      }
    
    

    ActivityFragmentLifecycle相关代码

      @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();
        }
      }
    

    总结:通过阅读源码,我们可以发现,Glide的生命周期取决于我们with方法传入的是Application 还是非Application ,所以,应该尽量使用非Application ,避免造成内存泄漏。

    你的认可,是我坚持更新博客的动力,如果觉得有用,就请点个赞,谢谢

    相关文章

      网友评论

        本文标题:【源码阅读】Glide源码阅读之with方法(一)

        本文链接:https://www.haomeiwen.com/subject/fqhwcqtx.html