范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

字节跳动一面之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方法传入所需要的上下文,主线程中一般传context,fragment,activity来实现对生命周期的绑定。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 .通过调用RequestManagerRetriever的get方法,传入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));     }   }
  RequestManagerRetriever的get方法中根据传入的参数不同,使用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 .通过调用RequestManagerRetriever的get方法,传入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的生命周期也会和整个应用程序一样。
  以上就是字节面试后总结的几个要点,还不会的同学赶紧学起来吧,感谢您的阅读,创造不易,如果您觉得本篇文章对您有帮助,请点击关注小编,您的支持就是小编创作的最大动力!

研究发现喝红茶与死亡率的关系每天喝红茶可能延寿,是真的吗?小明是一位茶艺爱好者,从小就跟着爷爷学习品茶,养成了每日饮茶的习惯。每天早晨,他都会泡一壶热茶,享受一下清新的茶香。但最近,小明却突然感到腰腹疼痛,并且尿液也开始出现异常。小明去医(每日一看)5个你不知道的冷知识1。绿茶和红茶其实不能一起泡,红茶和绿茶的茶性是不一样的,前者性温后者性寒,所以两者最好不要一起泡着喝,依绿茶和红茶的功效不同,夏天最好选择绿茶,冬天则多喝红茶为好,如果冬天喝绿茶CBA内斗或上演真实版狂飙大戏!2月最后一天深夜,中国篮球爆出惊天消息,CBA新疆广汇正式宣布退出CBA,公告痛斥中国篮协无理荒诞处罚指责周琦为巨额签字费诋毁俱乐部,更是把矛头指向了姚明同时担任篮协主席和CBA董CBA大爆冷,福建队轰19记三分球,上演17分大逆转李春江一脸不悦CBA联赛重燃战火,时隔三年,主客场制恢复的第一场比赛,福建队在主场迎战上海队。本场比赛,看点十足,这是王哲林被交易到上海队之后,首次回到福建队的主场。没想到,福建队爆发出巨大的能乌戈揭秘火辣美女调教蜘蛛侠阿尔瓦莱斯,她是谁?过去这4天蜘蛛侠阿尔瓦莱斯总算是从板凳的冰冷中暖过一口气来了,连续在英超和足总杯中获得首发。不仅都踢满全场,还打进一球,制造了对手一个乌龙球,送出一记助攻,两场比赛曼城也全都获得了上海男篮加时3分负福建,王哲林表现不佳,亚当斯砍45分获胜功臣上海男篮CBA联赛第三阶段首战赴客场挑战福建男篮,结果在加时赛以133比130负于对手,爆出大冷。第二阶段联赛结束上海男篮以17胜11负排名第六,福建男篮以6胜22负排名联赛第19今天,他走了!他一届世界杯攻入13球!梅西在他面前都是小娃娃!单届世界杯攻入13球创纪录至今无人能破他就是法国足球名宿方丹,他的家人向媒体透露,方丹已于今日离世,享年89岁!方丹在1958年瑞典世界杯的六场比赛中场场进球,包括在三四名对战西德曼联淘汰巴萨进入下一轮曼联在欧冠四分之一决赛中战胜巴塞罗那,这是一次历史性的胜利。这家英格兰俱乐部已经有十多年没有击败过加泰罗尼亚豪门了,而他们在老特拉福德以30的惊人胜利取得的胜利将永远留在曼联球迷的人一老,各种病都来了?中老年人做这3件事别太勤,对健康没益!拥有一个健康的身体是很多人都梦寐以求的,也是很多人追求的目标。随着时代的发展,现在除了老年人会注意养生和保养,有一部分年轻人也慢慢认识到了身体健康的重要性。很多类型的疾病都会在中老人体每天都消耗哪些营养素呢所见所得,都很科学一个人如果躺着不动,室温保持在2025,测出来的能量消耗称为基础代谢。一般来讲,男性为1400千卡天左右,女性在1300千卡天左右。除此之外,人体消耗主要包括以下滕哈赫会给马夏尔时间,拉什福德很健康,B费不想错过任何比赛直播吧3月1日讯曼联主帅滕哈赫在对阵西汉姆联的赛前发布会上,回答了关于几名队员的问题。马夏尔能否在3月份的国际比赛日前回到赛场?我当然希望如此,但我无法给出预计的时间。让他好好恢复