Glide源码之生命周期实现

Glide这个图片加载框架有个比较好的一点就是图片加载回根据Activity或Fragment生命周期的变化而变化,假如Activity或者Fragment销毁的时候,Glide会停止加载,以节省资源防止内存泄漏。至于Glide内部是怎么实现这个功能,这就是我们这一篇的内容。
首先,我们又来看一下Glide最基础的加载语句:

 Glide.with(this).load("url").into(imageview)

而实现生命周期的绑定最重要的语句就是Glide.with(this),在with()方法里会传入Activity或者Fragment的对象,以便进行绑定。with()方法代码如下(注:以Activity为例):

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

而with()方法里,与生命周期相关的就是get()方法,源码如下:

public RequestManager get(@NonNull Activity activity) {
    if (Util.isOnBackgroundThread()) {
      //假如是后台线程调用
      return get(activity.getApplicationContext());
    } else if (activity instanceof FragmentActivity) {
      return get((FragmentActivity) activity);
    } else {
      //上面的代码最终都会执行这个,所以这里是最重要的。
      assertNotDestroyed(activity);
      frameWaiter.registerSelf(activity);
      android.app.FragmentManager fm = activity.getFragmentManager();
      return fragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
    }
  }

上面的代码最终都会走最后一步,即获取FragmentManager,然后传给fragmentGet()方法,这个方法才是生成管理生命周期的关键:

private RequestManager fragmentGet(@NonNull Context context,
                                   @NonNull android.app.FragmentManager fm,
                                   @Nullable android.app.Fragment parentHint,
                                   boolean isParentVisible) {
    //创建RequestManagerFragment对象
    RequestManagerFragment current = getRequestManagerFragment(fm, parentHint);
    //获取请求管理类
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
     //假如没有,就生产该对象
      Glide glide = Glide.get(context);
      requestManager =factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      if (isParentVisible) {
        requestManager.onStart();
      }
      current.setRequestManager(requestManager);
    }
    return requestManager;
}

private RequestManagerFragment getRequestManagerFragment(
      @NonNull final android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint) {

    //从FragmentManager获取RequestManagerFragment看有没有
    RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
     //FragmentManager没有RequestManagerFragment,再从Glide缓存拿
      current = pendingRequestManagerFragments.get(fm);
      if (current == null) {
        //假如也没有,就生产新的RequestManagerFragment对象
        current = new RequestManagerFragment();
        current.setParentFragmentHint(parentHint);
        //将新的对象保存起来
        pendingRequestManagerFragments.put(fm, current);
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
        handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
      }
    }
    return current;
  }

上面的注释表明的基本流程,其中第一步就是获取RequestManagerFragment对象,再看看getRequestManagerFragment()里面的方法,,也没什么特别就是获取RequestManagerFragment再保存起来,那RequestManagerFragment是什么呢,其实RequestManagerFragment就是一个Fragment,

public class RequestManagerFragment extends Fragment {
    
  //省略....    
    
  public RequestManagerFragment() {
    this(new ActivityFragmentLifecycle());
  }

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

  //省略....    
    
}

我们刚才传入的Activity,生成一个Fragment用来干嘛?其实RequestManagerFragment是一个空的fragment,没有布局和View操作,与Activity绑定,仅仅用来监听生命周期。

在RequestManagerFragment创建的时候会通过构造器创建ActivityFragmentLifecycle对象,他是生命周期的回调监听,实现了Lifecycle接口。

public interface Lifecycle {
  void addListener(@NonNull LifecycleListener listener);

  void removeListener(@NonNull LifecycleListener listener);
}


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

}

Lifecycle负责实现注册和移除LifecycleListener接口,而ActivityFragmentLifecycle集成Lifecycle,同时还包含还包含onStart,onStop,onDestroy这三个方法,这三个方法是对应这个RequestManagerFragment也就是Frgament的onStart,onStop,onDestroy三个回调方法。当创建RequestManagerFragment结束后,当前页面加载的时候生命周期传递到RequestManagerFragment,就会执行对象的生命周期的方法,当执行onStart时候,调用ActivityFragmentLifecycle的onStart,当执行onStop时候,调用ActivityFragmentLifecycle的onStop由此类推。
不过还有一个问题,就是ActivityFragmentLifecycle的addListener是在哪里赋值的,当创建完RequestManagerFragment后,还会调

requestManager =factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);

生产RequestManager,监听就在这个时候,源码如下:

private static final RequestManagerRetriever.RequestManagerFactory DEFAULT_FACTORY = new RequestManagerRetriever.RequestManagerFactory() {
    //对应这个上面的build方法
    @NonNull
    public RequestManager build(@NonNull Glide glide, @NonNull Lifecycle lifecycle, @NonNull RequestManagerTreeNode requestManagerTreeNode, @NonNull Context context) {
        return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
    }
};

//生产RequestManager对象    
public RequestManager(
      @NonNull Glide glide,
      @NonNull Lifecycle lifecycle,
      @NonNull RequestManagerTreeNode treeNode,
      @NonNull Context context) {
    this(
        glide,
        lifecycle,
        treeNode,
        new RequestTracker(),
        glide.getConnectivityMonitorFactory(),
        context);
  }
  
RequestManager(
      Glide glide,
      Lifecycle lifecycle,
      RequestManagerTreeNode treeNode,
      RequestTracker requestTracker,
      ConnectivityMonitorFactory factory,
      Context context) {
    this.glide = glide;
    this.lifecycle = lifecycle;
    this.treeNode = treeNode;
    this.requestTracker = requestTracker;
    this.context = context;

    //省略代码...
  
    //设置生命周期监听事件
    if (Util.isOnBackgroundThread()) {
      Util.postOnUiThread(addSelfToLifecycle);
    } else {
      lifecycle.addListener(this);
    }
    lifecycle.addListener(connectivityMonitor);

    //省略代码...
  
  }  
  

上面的current.getGlideLifecycle()参数,该参数就是ActivityFragmentLifecycle,然后调用ActivityFragmentLifecycle的addListener方法进行注册,这样ActivityFragmentLifecycle生命周期管理类执行对应生命周期的时候就会调用RequestManager中的对应方法。对应的onStart就会开启网络请求,和设置ImageView监听到ImageView的onStart方法,onStart方法就这样监听到了。

当调ActivityFragmentLifecycle的onStart,onStop,onDestroy方法就会回调RequestManager的onStart,onStop,onDestroy方法,如下代码:

 public class RequestManager implements LifecycleListener, ……{
 
      @Override
      public synchronized void onStart() {
        //发起请求
        resumeRequests();
        //View的Target回调
        targetTracker.onStart();
      }
 
      @Override
      public synchronized void onStop() {
        //暂停请求
        pauseRequests();
         //View的Target回调
        targetTracker.onStop();
      }
 
      @Override
      public synchronized void onDestroy() {
        销毁请求
        targetTracker.onDestroy();
        //View的Target回调
        for (Target<?> target : targetTracker.getAll()) {
          clear(target);
        }
        //清空回调信息
        targetTracker.clear();
        requestTracker.clearRequests();
        lifecycle.removeListener(this);
        lifecycle.removeListener(connectivityMonitor);
        mainHandler.removeCallbacks(addSelfToLifecycle);
        glide.unregisterRequestManager(this);
      }
    }

这样就实现了Glide的生命周期管理,管理了请求开发,暂停,销毁这三个状态,使得更加节省资源,防止内存泄漏。也就是这个的基本流程

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容