美文网首页 移动 前端 Python Android Java
Glide 图片库使用和原理(一)

Glide 图片库使用和原理(一)

作者: zcwfeng | 来源:发表于2020-12-31 19:00 被阅读0次

    1 Glide 使用 ---4.11.0

    导入库

    implementation 'com.github.bumptech.glide:glide:4.11.0'
        annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
    

    1.1 简单使用

    class GlideTest : AppCompatActivity() {
        lateinit var binding: ActivityGlideTestBinding
        val imgUrl = "https://cn.bing.com/sa/simg/hpb/LaDigue_EN-CA1115245085_1920x1080.jpg"
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            binding = DataBindingUtil.setContentView(this, R.layout.activity_glide_test)
            binding.showImg.setOnClickListener {
    
                Glide.with(this).load(imgUrl).into(binding.contentImg)
    
            }
        }
    }
    

    1.2 其他部分用法

    val doc1 = """
        Glide 加载图片的方式
        // 加载本地图片
        File file = new File(getExternalCacheDir() + "/image.jpg");
        Glide.with(this).load(file).into(imageView);
    
        // 加载应用资源
        int resource = R.drawable.image;
        Glide.with(this).load(resource).into(imageView);
    
        // 加载二进制流
        byte[] image = getImageBytes();
        Glide.with(this).load(image).into(imageView);
    
        // 加载Uri对象
        Uri imageUri = getImageUri();
        Glide.with(this).load(imageUri).into(imageView);
    """
    
    val doc2 = """
        Glide 占位图,和一些属性实例
        Glide.with(this)
         .load(url)
         .asBitmap()
         .placeholder(R.drawable.loading)
         .error(R.drawable.error)
         .diskCacheStrategy(DiskCacheStrategy.NONE)
         .into(imageView);
         
        Glide.with(this).load(url)
         .asGif()
         .placeholder(R.drawable.loading).error(R.drawable.error).diskCacheStrategy(DiskCacheStrategy.NONE)
         .into(imageView);
         
        Glide.with(this).load(url).placeholder(R.drawable.loading.error(R.drawable.error).diskCacheStrategy(DiskCacheStrategy.NONE)
         .override(100, 100)
         .into(imageView);
    """
    

    2 三部曲with,load,into

    2.1

    第一步

    Glide#width(xxxx) 目标获取 RequestManager

    第二步
    Glide#load(xxx) 目标获取 RequestBuilder

    第三步
    Glide#into(xxx) 获取和处理Target

    1. 运行队列,等待队列
    2. 活动缓存
    3. 内存缓存
    4. 网络模型

    2.1.1 with

    监听Activity/Fragment生命周期

    当我们的Fragment或Activity不可见的时候暂停请求,当我们的Fragment或Activity可见的时候回复请求

    处理前台可见的 Activity / Fragment,提高资源利用率;
    在有必要时释放资源以避免在应用在后台时被杀死,提高稳定性;

    Glide#with(params)
    with会有很多重载方法,params参数有这些种类:(FragmentActivity,androidx.fragment.app.Fragment,android.app.Fragment,View)
    通过获取RequestManagerRetriever 进行检索

    RequestManagerRetriever#get方法 多个重载

    通过源码,我们会看到四个重载方法

    public RequestManager get(@NonNull Context context)
    
    public RequestManager get(@NonNull FragmentActivity activity)
    
    public RequestManager get(@NonNull Fragment fragment)
    
    public RequestManager get(@NonNull Activity activity)
    
    public RequestManager get(@NonNull View view)
    

    通过这些发放的分析,我们得出下面的分析

    生命周期的作用域(1.Application, 2.Activity, 3.Fragment)
    with 参数 作用域 代码中线程
    Application 子线程使用with
    View Fragment/Activity 主线程
    Fragment Fragment 主线程
    Activity Activity 主线程
    FragmentActivity Activity 主线程
    ServiceContext/ApplicationContext Application 主线程

    一共分为两种:
    第一种是作用域Application,它的生命周期是全局 的,不搞空白Fragment绑定Activity/Fragment
    第二种是作用域非Application,它的生命周期是,专门搞空白Fragment绑定 Activity/Fragment

    生成默认隐藏fragment ,我们发现有着几个方法

    private RequestManager supportFragmentGet(
          @NonNull Context context,
          @NonNull FragmentManager fm,
          @Nullable Fragment parentHint,
          boolean isParentVisible)
    
    private RequestManager fragmentGet(
          @NonNull Context context,
          @NonNull android.app.FragmentManager fm,
          @Nullable android.app.Fragment parentHint,
          boolean isParentVisible)
    
    
    

    supportFragmentGet---->getSupportRequestManagerFragment
    获取SupportRequestManagerFragment (Tag:FRAGMENT_TAG)的fragment

    private SupportRequestManagerFragment getSupportRequestManagerFragment(
          @NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
        SupportRequestManagerFragment current =
            (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
        if (current == null) {
          current = pendingSupportRequestManagerFragments.get(fm);
          if (current == null) {
            current = new SupportRequestManagerFragment();
            current.setParentFragmentHint(parentHint);
            if (isParentVisible) {
              current.getGlideLifecycle().onStart();
            }
            pendingSupportRequestManagerFragments.put(fm, current);
            fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
            handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
          }
        }
        return current;
      }
    

    fragmentGet---->getRequestManagerFragment
    获取RequestManagerFragment (Tag:FRAGMENT_TAG)的fragment

    private RequestManagerFragment getRequestManagerFragment(
          @NonNull final android.app.FragmentManager fm,
          @Nullable android.app.Fragment parentHint,
          boolean isParentVisible) {
        RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
        if (current == null) {
          current = pendingRequestManagerFragments.get(fm);
          if (current == null) {
            current = new RequestManagerFragment();
            current.setParentFragmentHint(parentHint);
            if (isParentVisible) {
              current.getGlideLifecycle().onStart();
            }
            pendingRequestManagerFragments.put(fm, current);
            fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
            handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
          }
        }
        return current;
      }
    
    生命周期的绑定

    【记录保存】 FragmentManager -SupportRequestManagerFragment

    RequestManagerRetriever .java

    final Map<FragmentManager, SupportRequestManagerFragment> pendingSupportRequestManagerFragments =
    new HashMap<>();

    supportFragmentGet----getSupportRequestManagerFragment

    1. 从FragmentManager中获取SupportRequestManagerFragment
    SupportRequestManagerFragment current =
            getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
    

    2.从该 Fragment 中获取 RequestManager

    RequestManager requestManager =current.getRequestManager();
    

    3.首次获取,则实例化 RequestManager

    ------> getSupportRequestManagerFragment
    1.1 尝试获取 FRAGMENT_TAG 对应的 Fragment
    1.2 尝试从临时记录中获取Fragment
    如果为获取到
    1.3 current==null---实例化 Fragment

    1.3.1 创建对象SupportRequestManagerFragment
    1.3.2 如果父层可见,则调用 onStart() 生命周期
    1.3.3 临时记录映射关系pendingSupportRequestManagerFragments.put(fm, current)
    1.3.4 提交 Fragment 事务
    1.3.5 post 一个消息
    handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
    

    -》post 一个消息分析: RequestManagerRetriever 本身实现了Handler的callback
    handleMessage中

    case ID_REMOVE_SUPPORT_FRAGMENT_MANAGER:
            FragmentManager supportFm = (FragmentManager) message.obj;
            key = supportFm;
            removed = pendingSupportRequestManagerFragments.remove(supportFm);
            break;
    

    就是为了避免 SupportRequestManagerFragment 在一个作用域中重复创建。

    因为 commitAllowingStateLoss() 是将事务 post 到消息队列中的,也就是说,事 务是异步处理的,而不是同步处理的。假设没有临时保存记录,一旦在事务异步等待 执行时调用了 Glide.with(...) ,就会在该作用域中重复创建 Fragment。

    生命周期的监听机制

    Glide内部会在 Activity/Fragment生命周期监听,网络变化监听,自动取消加 载或者重新加载

    框架为每个Activity 和 Fragment 作用域创建了 一个无UI的Fragment

    分析这个空Fragment---》 SupportRequestManagerFragment.java
    看下我们比较关心的代码

    ActivityFragmentLifecycle lifecycle
    
    public SupportRequestManagerFragment() {
        this(new ActivityFragmentLifecycle());
      }
    
      
      public SupportRequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
        this.lifecycle = lifecycle;
      }
    
     
      public void setRequestManager(@Nullable RequestManager requestManager) {
        this.requestManager = requestManager;
      }
    
     @Override
      public void onStart() {
        super.onStart();
        lifecycle.onStart();
      }
    
      @Override
      public void onStop() {
        super.onStop();
        lifecycle.onStop();
      }
    
      @Override
      public void onDestroy() {
        super.onDestroy();
        lifecycle.onDestroy();
        unregisterFragmentWithRoot();
      }
    

    回溯一下,RequestManagerRetriever.java 和 RequestManager.java

    1. 实例化RequestManager
    Glide glide = Glide.get(context);
          requestManager =
              factory.build(
                  glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
    
    1. RequestManager 工厂
    public interface RequestManagerFactory {
        @NonNull
        RequestManager build(
            @NonNull Glide glide,
            @NonNull Lifecycle lifecycle,
            @NonNull RequestManagerTreeNode requestManagerTreeNode,
            @NonNull Context context);
      }
    
    1. 默认工厂接口实现
    private static final RequestManagerFactory DEFAULT_FACTORY =
          new RequestManagerFactory() {
            @NonNull
            @Override
            public RequestManager build(
                @NonNull Glide glide,
                @NonNull Lifecycle lifecycle,
                @NonNull RequestManagerTreeNode requestManagerTreeNode,
                @NonNull Context context) {
              return new RequestManager(glide, lifecycle, requestManagerTreeNode, context);
            }
          };
    

    RequestManager.java 源码我们关心的部分

    final Lifecycle lifecycle;
    
    public RequestManager(
          @NonNull Glide glide,
          @NonNull Lifecycle lifecycle,
          @NonNull RequestManagerTreeNode treeNode,
          @NonNull Context context) {
    ......
        this.lifecycle = lifecycle;
        this.requestTracker = requestTracker;// 生命周期回调
    。。。
    if (Util.isOnBackgroundThread()) {
          mainHandler.post(addSelfToLifecycle);
        } else {// 添加监听
          lifecycle.addListener(this);
        }
    。。。
    
    public synchronized void onDestroy() {
        targetTracker.onDestroy();
        ......
        lifecycle.removeListener(this);//remove 监听
      }
    }
    

    实例化 RequestManager 时需要一个 Lifecycle对象,这个对象是 在无界面 Fragment 中创建的,当 Fragment 的生命周期变化时,就是通过这个 Lifecycle 对象将事件分发到RequestManager

    生命周期的回调

    RequestsManger 收到的回调ConnectivityMonitor

    public interface LifecycleListener {
        void onStart();
        void onStop();
        void onDestroy();
    }
    

    Activity/Fragment 不可见时暂停请求 (onStop() ) 函数 Activity/Fragment 可见时恢复请求 (onStart() ) 函数 Activity/Fragment 销毁时销毁请求 (onDestroy() )函数

    ---》 RequestManger 操作 requestTracker

    @Override
      public synchronized void onStop() {
        pauseRequests();
        targetTracker.onStop();
      }
    
    @Override
      public synchronized void onStart() {
        resumeRequests();
        targetTracker.onStart();
      }
    
      public synchronized void resumeRequests() {
        requestTracker.resumeRequests();
      }
    
    public synchronized void pauseRequests() {
        requestTracker.pauseRequests();
      }
    
    @Override
      public synchronized void onDestroy() {
        targetTracker.onDestroy();
        for (Target<?> target : targetTracker.getAll()) {
          clear(target);
        }
        targetTracker.clear();
        requestTracker.clearRequests();
        lifecycle.removeListener(this);
        lifecycle.removeListener(connectivityMonitor);
        mainHandler.removeCallbacks(addSelfToLifecycle);
        glide.unregisterRequestManager(this);
      }
    

    相关文章

      网友评论

        本文标题:Glide 图片库使用和原理(一)

        本文链接:https://www.haomeiwen.com/subject/wdxhoktx.html