字节跳动一面之Glide生命周期管理面试总结

本文通过在字节面试遇到的问题总结而出,如有不对的地方,请及时批评指正。篇幅较长,请耐心阅读。如果您想了解其他框架源码,欢迎评论区留言!

篇幅较长,请耐心阅读[玫瑰]

简介

Glide是一个优秀的图片加载框架,支持多种数据源,功能强大,性能高。如图所示:

使用步骤

1.在build.gradle中添加glide引用

implementation 'com.github.bumptech.glide:glide:4.12.0'

2.使用glide加载图片

Glide.with(this).load(BASE_PIC_URL).into(img_user)

源码分析

设计模式

1.单例模式

Glide使用了单例设计模式,通过双重校验锁机制不仅保证了Glide对象的全局单例,而且解决了多线程环境下的并发安全问题。

2.工厂设计模式

Glide内部的创建RequestManager对象时使用了工厂设计模式,通过定义RequestManagerFactory抽象接口,让其子类创建RequestManager对象,隐藏其内部创建逻辑。

3.建造者设计模式

Glide使用了静态类GlideBuilder构建Glide对象,将Glide的各种属性封装到GlideBuilder中,根据不同的属性设置构建不同功能的Glide对象。简化Glide的构建过程。

生命周期绑定

主线程中使用

1 .Glide使用With方法传入所需要的上下文,主线程中一般传contextfragmentactivity来实现对生命周期的绑定。

public static RequestManager with(@NonNull Context context) 
public static RequestManager with(@NonNull Activity activity) 
public static RequestManager with(@NonNull Fragment fragment) 
public static RequestManager with(@NonNull FragmentActivity activity)

2 .下面以activity为例,参数传入activity。

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

3 .通过调用RequestManagerRetrieverget方法,传入activity参数返回RequestManager对象。RequestManager主要负责管理Glide的请求和启动。

  @NonNull
  public RequestManager get(@NonNull Activity activity) {
      //判断是否是后台线程
    if (Util.isOnBackgroundThread()) {
      return get(activity.getApplicationContext());
    } else if (activity instanceof FragmentActivity) {
      return get((FragmentActivity) activity);
    } else {
      //判断当前activity没有被销毁,否则抛出异常  
      assertNotDestroyed(activity);
      frameWaiter.registerSelf(activity);
      //获取activity中的FragmentManager 
      android.app.FragmentManager fm = activity.getFragmentManager();
      //通过fragmentGet方法 ,创建并返回 RequestManager
      return fragmentGet(activity, fm, /*parentHint=*/ null, isActivityVisible(activity));
    }
  }

RequestManagerRetrieverget方法中根据传入的参数不同,使用Util.isOnBackgroundThread判断子线程和主线程分别进行不同的处理。主线程中最终都是调用fragmentGet方法。注意,由于这里的参数是activity,获取的是fragmentManager,如果传入的是fragment,则获取的childFragmentManager.

4 .fragmentGet方法主要是通过RequestManagerFragment来获取RequestManager,如果没有获取到,则通过工厂模式进行创建。同时传入fragment的getGlideLifecycle这个lifecycle是重点,需要注意

private RequestManager fragmentGet(
      @NonNull Context context,
      @NonNull android.app.FragmentManager fm,
      @Nullable android.app.Fragment parentHint,
      boolean isParentVisible) {
    //通过fragmentManager获取RequestManagerFragment
    RequestManagerFragment current = getRequestManagerFragment(fm, parentHint);
    //获取RequestManagerFragment中的requestManager
    RequestManager requestManager = current.getRequestManager();
    //判断requestManager
    if (requestManager == null) {
    //如果requestManager为空,则通过工厂设计模式创建出requestManager 
      Glide glide = Glide.get(context);
      requestManager =
          factory.build(
              glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
      //如果activity显示出来,则执行requestManager的onStart方法
        
      if (isParentVisible) {
        requestManager.onStart();
      }
      current.setRequestManager(requestManager);
    }
    return requestManager;
  }

5 .创建RequestManagerFragment,这里创建一个空白页面的RequestManagerFragment并且绑定到当前activity中。

@NonNull
  private RequestManagerFragment getRequestManagerFragment(
      @NonNull final android.app.FragmentManager fm, @Nullable android.app.Fragment parentHint) {
      //通过tag获取fragmentManager中保存的fragment
      RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
       //如果获取不到,则进一步通过 pendingRequestManagerFragments Map中获取
      current = pendingRequestManagerFragments.get(fm);
      if (current == null) {
        //如果还是获取不到,则进行创建  
        current = new RequestManagerFragment();
        current.setParentFragmentHint(parentHint);
         //同时保存到map中 
        pendingRequestManagerFragments.put(fm, current);
         //然后添加到当前activity中 
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
        //将这个添加动作通过handler发送给系统处理  
        handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
      }
    }
    return current;
  }

6 .RequestManagerFragment的构造函数创建了ActivityFragmentLifecycle用来监听RequestManagerFragment的生命周期 onStart(),onStop(),onDestroy()

public SupportRequestManagerFragment() {
    this(new ActivityFragmentLifecycle());
 }
public SupportRequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
    this.lifecycle = lifecycle;
  }
 @Override
  public void onStart() {
    super.onStart();
    lifecycle.onStart();
  }

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

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

最后在fragmentGet方法中ActivityFragmentLifecycle通过工厂设计模式传给RequestManager并返回。

7 .ActivityFragmentLifecycle继承于Lifecycle接口。

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

8 .RequestManager拿到这个lifecycle,进行绑定监听RequestManagerFragment生命周期。

 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监听   
      lifecycle.addListener(this);
    }
    lifecycle.addListener(connectivityMonitor);
    ..............
  }

9 .通过生命周期的绑定处理对应的业务逻辑和资源释放等功能。

 public synchronized void onStart() {
    //开始请求 
    resumeRequests();
    targetTracker.onStart();
  }
  @Override
  public synchronized void onStop() {
  //开始停止
    pauseRequests();
    targetTracker.onStop();
  }
  @Override
  public synchronized void onDestroy() {
    targetTracker.onDestroy();
     //释放资源  
    targetTracker.clear();
    requestTracker.clearRequests();
    lifecycle.removeListener(this);
    lifecycle.removeListener(connectivityMonitor);
    Util.removeCallbacksOnUiThread(addSelfToLifecycle);
    glide.unregisterRequestManager(this);
  }

总结如下图所示:

Glide在主线程中使用时,通过创建一个空白的fragment添加到当前Activity/Fragment中,用来监听当前页面的生命周期变化,进行图片的显示或资源的释放。

子线程中使用


1 . Glide在子线程中使用只能传入applicationContext。

public static RequestManager with(@NonNull Context context)

2 .通过调用RequestManagerRetrieverget方法,传入activity参数返回RequestManager对象。RequestManager主要负责管理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
             && ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
        return get(((ContextWrapper) context).getBaseContext());
      }
    }
    //子线程返回applicationManager
    return getApplicationManager(context);
  }

3 .在getApplicationManager方法中通过双重校验锁单例方式返回applicationManager,applicationManager的创建使用了工厂设计模式,隐藏了applicationManager的内部创建细节。

 @NonNull
  private RequestManager getApplicationManager(@NonNull Context context) {
    if (applicationManager == null) {
      synchronized (this) {
        if (applicationManager == null) {
          Glide glide = Glide.get(context.getApplicationContext());
          applicationManager =
              factory.build(
                  glide,
                  new ApplicationLifecycle(),
                  new EmptyRequestManagerTreeNode(),
                  context.getApplicationContext());
        }
      }
    }

    return applicationManager;
  }

4 .getApplicationManager创建applicationManager时传入了ApplicationLifecycle作为生命周期监听。

 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;
    .............
     //如果是子线程,通过使用Handler切换到主线程
    if (Util.isOnBackgroundThread()) {
      Util.postOnUiThread(addSelfToLifecycle);
    } else {
      lifecycle.addListener(this);
    }
     ................
   }

5 .RequestManager拿到这个lifecycle,使用Handler切换到主线程进行绑定监听Application生命周期。

 private final Runnable addSelfToLifecycle =
      new Runnable() {
        @Override
        public void run() {
          lifecycle.addListener(RequestManager.this);
        }
      };

6 .通过绑定Application的onStart()方法进行请求处理。

public synchronized void onStart() {
    //开始请求 
    resumeRequests();
    targetTracker.onStart();
  }

总结如下图所示:

当Glide在子线程中使用时,只需要监听application的onStart方法进行业务请求的处理,application销毁时,整个应用程序都会被销毁,Glide也会跟随着应用销毁而进行资源释放。所以在子线程中使用,由于传入的context是applicationContext,Glide的生命周期也会和整个应用程序一样。

以上就是字节面试后总结的几个要点,还不会的同学赶紧学起来吧,感谢您的阅读,创造不易,如果您觉得本篇文章对您有帮助,请点击关注小编,您的支持就是小编创作的最大动力!

展开阅读全文

页面更新:2024-05-16

标签:生命周期   线程   主线   绑定   字节   对象   工厂   参数   模式   方法   资源

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top