深入Glide 1--Glide框架结构与生命周期管理

上两篇文章主要介绍Glide的基础,缓存以及图片的加载过程,接下来我们开始正式进入Glide的讲解,通过下面的学习,我们主要会了解到

  • Glide如何绑定Activity、Fragment生命周期变化
  • Glide如何监听内存变化、网络变化
  • Glide如何处理请求的生命周期

生命周期相关UML类图

Glide流程.png

生命周期绑定

Glide生命周期绑定是从入口单例类Glide开始的,通过with()多个重载方法来实现对生命周期的绑定工作。

public static RequestManager with(Fragment fragment)  
public static RequestManager with(FragmentActivity activity)  
public static RequestManager with(Activity activity)  
public static RequestManager with(Context context)

以Activity的参数为例:

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

RequestManagerRetriever是一个单例类,可以理解为一个工厂类,通过get方法接收不同的参数,来创建RequestManager。

public RequestManager get(Activity activity) {
    if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
        return get(activity.getApplicationContext());
    } else {
        assertNotDestroyed(activity);
        android.app.FragmentManager fm = activity.getFragmentManager();
        return fragmentGet(activity, fm);
    }
}
public RequestManager get(android.app.Fragment fragment) {
    if (fragment.getActivity() == null) {
        throw new IllegalArgumentException("You cannot start a load on a fragment before it is attached");
    }
    if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
        return get(fragment.getActivity().getApplicationContext());
    } else {
        android.app.FragmentManager fm = fragment.getChildFragmentManager();
        return fragmentGet(fragment.getActivity(), fm);
    }
}

如果是在子线程进行的with操作,那么Glide将默认使用ApplicationContext,可以理解为不对请求的生命周期进行管理,通过Activity拿到FragmentManager,并将创建RequestManager的任务传递下去。最终都走到了fragmentGet方法,注意细微区别是Activity传的参数的是Activity的FragmentManager,Fragment传的参数的是ChildFragmentManager,这两者不是一个东西。

RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {
    //获取RequestManagerFragment,并获取绑定到这个fragment的RequestManager
    RequestManagerFragment current = getRequestManagerFragment(fm);
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
    //如果获取RequestManagerFragment还没有绑定过RequestManager,那么就创建RequestManager并绑定到RequestManagerFragment
        requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
        current.setRequestManager(requestManager);
    }
    return requestManager;
}

创建RequestManagerFragment

这个方法创建了一个fragment,并且创建并绑定了一个RequestManager,看看getRequestManagerFragment如何获取的RequestManagerFragment。

RequestManagerFragment getRequestManagerFragment(final android.app.FragmentManager fm) {
    //尝试根据id去找到此前创建的RequestManagerFragment
    RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
        //如果没有找到,那么从临时存储中寻找
        current = pendingRequestManagerFragments.get(fm);
        if (current == null) {
            //如果仍然没有找到,那么新建一个RequestManagerFragment,并添加到临时存储中。
            //然后开启事务绑定fragment并使用handler发送消息来将临时存储的fragment移除。
            current = new RequestManagerFragment();
            pendingRequestManagerFragments.put(fm, current);
            fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
            handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
        }
    }
    return current;
}

这里有个问题,为什么需要使用pendingRequestManagerFragments这样一个集合来临时存储一下fragment,然后又马上通过handler发送消息移除?这其实是跟主线程的Looper机制和Fragment的事务机制有关的。我们知道,android中的主线程是一个闭环,通过Handler发送消息到MessageQueue,然后通过Looper轮询获取消息并交给Handler处理。如下面一个常见场景:

Glide.with(this).load(url_1).into(mImageView_1);
Glide.with(this).load(url_2).into(mImageView_2);

这段代码通过Glide加载了两张图片并设置到了两个ImageView上,当以上代码块执行时,其所属的代码群的Message刚刚从MessageQueue中取出正在被处理,我们假设这个Message为m1,并且这个MessageQueue中没有其他消息。此时情形是这样的:

但是m2这个消息并不会马上被处理,这是因为m1还有代码还没有执行完毕,也就是说这个fragment并不会马上被绑定,此时m1继续向下执行到第二句代码

Glide.with(this).load(url_2).into(mImageView_2);

当这句代码走到getRequestManagerFragment时,如果在m1时,我们不将fragment临时存储在pendingRequestManagerFragments中,由于m2还没有被处理,那么

RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);

必然是找不到这个fragment的,那么就会导致重新创建一个新的重复的fragment,并开启事务绑定,这显然是不合情理的,因为Glide需要保证rootFragment的唯一性,rootFragment即fragment依附或者没有fragment依附的activity所创建的最上层RequestManagerFragment。
接着往下看RequestManagerFragment的构造方法做了什么。

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

直接创建一个ActivityFragmentLifecycle,这个类实际是一个生命周期回调的管理类,实现了Lifecycle接口。所有的LifecycleListener会添加到一个集合中,当RequestManagerFragment生命周期方法触发时,会调用ActivityFragmentLifecycle相应生命周期方法,这个方法然后再遍历调用所有LifecycleListener的生命周期方法,以onStart生命周期方法为例,RequestManagerFragment中:

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

然后ActivityFragmentLifecycle中:

void onStart() {
    isStarted = true;
    for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
        lifecycleListener.onStart();
    }
}

rootRequestManagerFragment

面UML图上,可以知道RequestManagerFragment还有一个rootRequestManagerFragment的成员变量,Glide每创建一个RequestManagerFragment,都会尝试实例化rootRequestManagerFragment,这个fragment即顶级的Activity所创建的RequestManagerFragment,相关代码

public void onAttach(Activity activity) {
    super.onAttach(activity);
    rootRequestManagerFragment = RequestManagerRetriever.get()
            .getRequestManagerFragment(getActivity().getFragmentManager());
    if (rootRequestManagerFragment != this) {
        rootRequestManagerFragment.addChildRequestManagerFragment(this);
    }
}

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

可以看到,不管当前的RequestManagerFragment是通过何种方式创建的,都会在OnAttach时,拿到当前所绑定的Activity的FragmentManager来初始化一个RequestManagerFragment,这个RequestManagerFragment有可能是自身,有可能已经被初始化过了,比如是通过with(Activity activity)的方式初始化的,那么很显然

RequestManagerRetriever.get().getRequestManagerFragment(getActivity().getFragmentManager());

这句代码拿到的会是自己本身,而如果是通过with(Fragment fragment)的形式创建的,rootRequestManagerFragment将指向当前fragment绑定到Activity所绑定的RequestManagerFragment,如果该Activity没有绑定过,那么会开启事务绑定一个RequestManagerFragment。并且如果自己不是rootRequestManagerFragment的话,那么将会把自己保存到rootRequestManagerFragment中的一个集合:

private void addChildRequestManagerFragment(RequestManagerFragment child) {
    childRequestManagerFragments.add(child);
}

简而言之,Glide会为Activity创建一个RequestManagerFragment做为rootFragment,并保存该Activity底下所有Fragment(如果有的话)所创建的RequestManagerFragment。

你可能感兴趣的:(深入Glide 1--Glide框架结构与生命周期管理)