字节跳动一面之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的生命周期也会和整个应用程序一样。
以上就是字节面试后总结的几个要点,还不会的同学赶紧学起来吧,感谢您的阅读,创造不易,如果您觉得本篇文章对您有帮助,请点击关注小编,您的支持就是小编创作的最大动力!