Glide 生命周期绑定分析(3.7.0为例 1)


Glide 加载图片时,我们知道它会根据传入的上下文决定它的生命周期,如果传入的是 Activity 或 Fragment,那么如果页面隐藏或销毁时,图片还没从网络上获取成功,它会自己停止加载图片;该页面重新出现在前台时,会重新加载,那么 Glide 是怎么做到的呢?在 Activity 中添加一个 Fragment,Fragment 的生命周期会随着 Activity 的生命周期变化而变化;同样,Fragment 中也可以嵌套 Fragment。反应快的,看到这就反应过来了,Glide 其实就是通过 Fragment 来控制生命周期的。

Glide 的 with() 方法,会传入几种不同的形参,我们以 FragmentActivity 为例,

    public static RequestManager with(FragmentActivity activity) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
        return retriever.get(activity);
    }

RequestManagerRetriever 是个单利,我们看看它对应的 get() 方法

    public RequestManager get(FragmentActivity activity) {
        if (Util.isOnBackgroundThread()) {
            return get(activity.getApplicationContext());
        } else {
            assertNotDestroyed(activity);
            FragmentManager fm = activity.getSupportFragmentManager();
            return supportFragmentGet(activity, fm);
        }
    }

这个方法中会先判断当前线程是否是UI线程,如果不是,则调用重载方法,参数为 Application;如果是UI线程,先检查 activity 是否被销毁,然后获取一个 FragmentManager,把它们作为参数,传入 supportFragmentGet() 方法中

    RequestManager supportFragmentGet(Context context, FragmentManager fm) {
        SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm);
        RequestManager requestManager = current.getRequestManager();
        if (requestManager == null) {
            requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
            current.setRequestManager(requestManager);
        }
        return requestManager;
    }


这个方法中主要牵涉到两个对象:RequestManager 和 SupportRequestManagerFragment,看名字,一个是加载图片管理器,另外一个是对管理器提供支持的Fragment,先看看 getSupportRequestManagerFragment(fm) 方法

    SupportRequestManagerFragment getSupportRequestManagerFragment(final FragmentManager fm) {
        SupportRequestManagerFragment current = (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
        if (current == null) {
            current = pendingSupportRequestManagerFragments.get(fm);
            if (current == null) {
                current = new SupportRequestManagerFragment();
                pendingSupportRequestManagerFragments.put(fm, current);
                fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
                handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
            }
        }
        return current;
    }

这个方法逻辑比较简单,先从事务管理器中根据 TAG 来找对应的Fragment,如果为空,则从集合中查找,如果还没有,则创建一个,并添加到集合中,然后开启一个事物,把生成的Fragment添加进去,然后通过Handler发送一条消息,在Handler接收器中,把管理器从集合中移除,为什么这么做,感觉是在做多余的操作?我也是看了一片文章才明白,比如说同一个页面 onCreate() 中两个 ImageView a和b 同时用 Glide 来加载图片,都执行了 getSupportRequestManagerFragment() 方法,a执行时,管理器 findFragmentByTag()找TAG标签的Fragment为空,则执行下面操作,创建 SupportRequestManagerFragment 并添加到事物管理器中;此时b也进入了这个方法,由于a中向管理器中添加了Fragment,此时应该不为null吧?实际上,findFragmentByTag(FRAGMENT_TAG) 还是 null,为什么呢?因为事务管理器添加Fragment的 enqueueAction() 方法,也是通过 Handler 来执行具体的逻辑,那么此时,onCreate() 还在执行,事务管理器的中 Handler 操作的 Runnable,还在队列中等待,如果没有 pendingSupportRequestManagerFragments 这个集合临时存储数据,则 SupportRequestManagerFragment 会被重复创建,造成浪费,并且也不符合逻辑。

继续看 supportFragmentGet(Context context, FragmentManager fm) 方法,里面还有一个 RequestManager,它new出来的,并且把 context 和 current 中的对象当做参数传入构造方法中,并且也把创建好的 requestManager 设置到 SupportRequestManagerFragment 中,我们来看看 RequestManager 类

   public RequestManager(Context context, Lifecycle lifecycle, RequestManagerTreeNode treeNode) {
        this(context, lifecycle, treeNode, new RequestTracker(), new ConnectivityMonitorFactory());
    }

    RequestManager(Context context, final Lifecycle lifecycle, RequestManagerTreeNode treeNode,
            RequestTracker requestTracker, ConnectivityMonitorFactory factory) {
        this.context = context.getApplicationContext();
        this.lifecycle = lifecycle;
        this.treeNode = treeNode;
        this.requestTracker = requestTracker;
        this.glide = Glide.get(context);
        this.optionsApplier = new OptionsApplier();

        ConnectivityMonitor connectivityMonitor = factory.build(context,
                new RequestManagerConnectivityListener(requestTracker));

        if (Util.isOnBackgroundThread()) {
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    lifecycle.addListener(RequestManager.this);
                }
            });
        } else {
            lifecycle.addListener(this);
        }
        lifecycle.addListener(connectivityMonitor);
    }

看构造方法,除了传进来的形参,还有 RequestTracker 和 ConnectivityMonitorFactory; RequestManager 实现了 LifecycleListener 接口,所以添加到 lifecycle集合中,connectivityMonitor 也被添加到集合中,它又是什么呢? ConnectivityMonitorFactory 看名字是个工厂类,看一下

public class ConnectivityMonitorFactory {
    public ConnectivityMonitor build(Context context, ConnectivityMonitor.ConnectivityListener listener) {
        final int res = context.checkCallingOrSelfPermission("android.permission.ACCESS_NETWORK_STATE");
        final boolean hasPermission = res == PackageManager.PERMISSION_GRANTED;
        if (hasPermission) {
            return new DefaultConnectivityMonitor(context, listener);
        } else {
            return new NullConnectivityMonitor();
        }
    }
}

这里做了个判断,是否有获取网络信息状态的权限,如果有则返回 DefaultConnectivityMonitor,如果无,则返回 NullConnectivityMonitor,NullConnectivityMonitor 里面的方法都是空的,没有相应的回调;注意 DefaultConnectivityMonitor 类,里面的逻辑相对简单,比较好理解,但它的思路很赞,明明是个监听网络变化的广播,把事件回调出去就行了,但这里加个注册监听和取消监听的逻辑, onStart() 和 onStop() 方法,这两个方法是何时触发的,一会再说;注册广播后,网络有了变化,会做个简单的逻辑比较,然后通过 listener 把事件回调出去,这里的 listener 就是 RequestManager 中的 RequestManagerConnectivityListener,它构造里面还有个 RequestTracker

    private static class RequestManagerConnectivityListener implements ConnectivityMonitor.ConnectivityListener {
        private final RequestTracker requestTracker;

        public RequestManagerConnectivityListener(RequestTracker requestTracker) {
            this.requestTracker = requestTracker;
        }

        @Override
        public void onConnectivityChanged(boolean isConnected) {
            if (isConnected) {
                requestTracker.restartRequests();
            }
        }
    }

也就是说网络变化,有网络后,最终还是执行 RequestTracker 的 restartRequests() 方法,看名字也是恢复请求。

RequestManager 中另外一个地方就是 lifecycle ,它是个接口,它把 RequestManager 和 ConnectivityMonitor 通过 addListener() 方法添加起来,我们看看它是什么?

SupportRequestManagerFragment 的 getLifecycle() 和 getRequestManagerTreeNode() 返回的值当做形参传入了 RequestManager 的构造方法中,

    private final RequestManagerTreeNode requestManagerTreeNode = new SupportFragmentRequestManagerTreeNode();

    public SupportRequestManagerFragment() {
        this(new ActivityFragmentLifecycle());
    }

    // For testing only.
    @SuppressLint("ValidFragment")
    public SupportRequestManagerFragment(ActivityFragmentLifecycle lifecycle) {
        this.lifecycle = lifecycle;
    }

看代码,一个是 RequestManagerTreeNode,一个是 ActivityFragmentLifecycle,先看 ActivityFragmentLifecycle

class ActivityFragmentLifecycle implements Lifecycle {
    private final Set<LifecycleListener> lifecycleListeners =
            Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>());
    private boolean isStarted;
    private boolean isDestroyed;

    @Override
    public void addListener(LifecycleListener listener) {
        lifecycleListeners.add(listener);

        if (isDestroyed) {
            listener.onDestroy();
        } else if (isStarted) {
            listener.onStart();
        } else {
            listener.onStop();
        }
    }

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

它是一个生命周期管理器,用一个集合添加 LifecycleListener 对象,然后遍历,调用对应的回调方法;isStarted 和 isDestroyed 是记录回调状态的,
而 addListener(LifecycleListener listener) 方法中,添加 listener 时,根据这两个属性,判断当前管理器是处于哪一个阶段,直接执行相应的回调,写法比较巧。SupportRequestManagerFragment 中的 lifecycle 添加了各种回调,由于 Activity 切入前台或后台,或跳转其他页面, Fragment 自己的声明周期也会变化,所以

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

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

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

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        if (requestManager != null) {
            requestManager.onLowMemory();
        }
    }

这里的 lifecycle 就是上面 RequestManager 中的 lifecycle,Fragment 生命周期变化,就会调用相应的方法,RequestManager 和RequestManagerConnectivityListener都实现了 LifecycleListener,它俩由 Fragment 控制。内存不足,Fragment也会触发 onLowMemory() 方法,此时调用了 requestManager 的 onLowMemory() 方法,而 RequestManager 中,则是调用 Glide 的方法,清除内存

    public void onLowMemory() {
        glide.clearMemory();
    }

再看看 requestManagerTreeNode 这个集合,不太理解;rootRequestManagerFragment 则是判断是否是当前Fragment,

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        rootRequestManagerFragment = RequestManagerRetriever.get()
                .getSupportRequestManagerFragment(getActivity().getSupportFragmentManager());
        if (rootRequestManagerFragment != this) {
            rootRequestManagerFragment.addChildRequestManagerFragment(this);
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        if (rootRequestManagerFragment != null) {
            rootRequestManagerFragment.removeChildRequestManagerFragment(this);
            rootRequestManagerFragment = null;
        }
    }

也是随Fragment的声明周期控制的,由于 Fragment 可以嵌套 Fragment,所以就有上面的写法,getDescendantRequestManagerFragments() 方法是被 SupportFragmentRequestManagerTreeNode的方法调用的,它这里应该是获取属于自己子Fragment的RequestManager,用于 Fragment嵌套Fragment的情况,调用的地方是 RequestManager 中的 resumeRequestsRecursive() 方法, 我们可以在代码中直接调用  Glide.with(this).pauseRequestsRecursive();。这里大概知道怎么回事,不敢乱讲,怕说错,望有懂的大神指教。
    
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值