zoukankan      html  css  js  c++  java
  • Android面试题:讲一讲Glide的原理

    这个问题是字节跳动面试官问的,当时没看过图片异步加载框架的原理,只能跟他说会用。今天仔细看了看原理感觉也没那么难。

    Gilde的使用方法也很简单:

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

    with绑定生命周期,load指定加载资源,into指明加载目标

    生命周期绑定

    源码解读

    Glide.class和RequestManagerRetriever.class,主要用来获得RequestManager

    //with返回一个RequestManager
    public
    static RequestManager with(Activity activity) { return getRetriever(activity).get(activity); } //无论调用的是哪个with重载方法,最后都会到这里 public RequestManager get(Activity activity) { if (Util.isOnBackgroundThread()) { return get(activity.getApplicationContext()); } else { assertNotDestroyed(activity); android.app.FragmentManager fm = activity.getFragmentManager(); return fragmentGet(activity, fm, null); } } //这里新建了一个没有视图的RequestManagerFragment private RequestManager fragmentGet(Context context, android.app.FragmentManager fm, android.app.Fragment parentHint) { RequestManagerFragment current = getRequestManagerFragment(fm, parentHint); RequestManager requestManager = current.getRequestManager(); if (requestManager == null) { Glide glide = Glide.get(context);
         //绑定requestManager和FragmentLifecycle requestManager
    = factory.build( glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context); current.setRequestManager(requestManager); } return requestManager; }

    RequestManagerFragment.class中持有一个lifecycle,在Fragment进入关键生命周期时会主动通知lifecycle执行相关方法

    public class RequestManagerFragment extends Fragment {
      ...
      private final ActivityFragmentLifecycle 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();
      }  }

    ActivityFragmentLifecycle.class中持有一个lifecycleListeners,在Fragment进入关键生命周期时Lifecycle会通知他的所有Listener

    class ActivityFragmentLifecycle implements Lifecycle {
     ...
    private final Set<LifecycleListener> lifecycleListeners;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(); } }
    ... }

    RequestManger.class关键生命周期中处理加载任务

    @Override
    public void onStart() {
        resumeRequests();
        targetTracker.onStart();
    }
    
    @Override
    public void onStop() {
        pauseRequests();
        targetTracker.onStop();
    }
    
    @Override
    public void onDestroy() {
        targetTracker.onDestroy();
        for (Target<?> target : targetTracker.getAll()) {
            clear(target);
        }
        targetTracker.clear();
        requestTracker.clearRequests();
    }

    总结

    1. Glide在加载绑定了Activity的生命周期。
    2. 在Activity内新建一个无UI的Fragment,这个特殊的Fragment持有一个Lifecycle。通过Lifecycle在Fragment关键生命周期通知RequestManger进行相关的操作。
    3. 在生命周期onStart时继续加载,onStop时暂停加载,onDestory是停止加载任务和清除操作。

    缓存机制

    缓存方式

    1. DiskCacheStrategy.NONE 不缓存文件
    2. DiskCacheStrategy.SOURCE 只缓存原图
    3. DiskCacheStrategy.RESULT 只缓存最终加载的图(默认的缓存略)
    4. DiskCacheStrategy.ALL 同时缓存原图和结果图

    缓存键

    EngineKey key = keyFactory.buildKey(model, signature, width, height, transformations,
            resourceClass, transcodeClass, options);

    缓存一般通过键值对的形式,缓存的键包括图片的宽、高、signature等参数。

    图片加载策略

    1. 首先从ActivateResource获取,是个值为弱引用的Map
    2. MemoryCache和DiskCache是LruCache

    MemoryCache和ActiveResource的关系

    图片加载时会从MemoryCache移到ActivateResouce,生命周期结束后会缓存至MemoryCache,所以内存中至多有一份缓存。

     主要线程池

    public Glide build(@NonNull Context context) {
        if (sourceExecutor == null) {
            sourceExecutor = GlideExecutor.newSourceExecutor();//创建网络加载线程池对象
        }
    
        if (diskCacheExecutor == null) {
            diskCacheExecutor = GlideExecutor.newDiskCacheExecutor();//创建磁盘加载线程池对象
        }
    
        if (animationExecutor == null) {
            animationExecutor = GlideExecutor.newAnimationExecutor();//创建动画加载线程池对象
        }
        
    }
  • 相关阅读:
    html页面怎样能够自适应电脑屏幕宽度
    js语法大全
    DevExtreme- jQuery 表格组件-DataGrid
    DevExtreme 图表组件
    C# 中的委托和事件
    SQL Server游标的使用
    Oracle11g使用exp导出空表
    PowerDesigner设计Name和Comment 替换
    Toad for Oracle 快捷键
    Windows 命令大全
  • 原文地址:https://www.cnblogs.com/billshen/p/13306285.html
Copyright © 2011-2022 走看看