Glide(一)生命周期的监听

Glide的生命周期监听

惠猛 2022.03.24

  Glide实现对所属activity或者fragment生命周期监听的方法是:通过一个隐形的fragment,嵌入到所要监听的fragment
  或者activity中,当被监听的fragment或者activity生命周期发生变化时,该隐形的fragment的相关生命周期函数也会被调用,
  这样就实现了对外部activity或者fragment的监听。在Activity内新建一个无UI的Fragment,这个特殊的Fragment
  持有一个Lifecycle。通过Lifecycle在Fragment关键生命周期通知RequestManger进行相关的操作。
在生命周期onStart时继续加载,onStop时暂停加载,onDestory是停止加载任务和清除操作。

在这里插入图片描述

代码中,Glide通过with绑定要监听的对象。

class MainActivity : AppCompatActivity() {
    
    
    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
		
        // 通过with,绑定Glide要监听的对象
        Glide.with(this)
    }

    override fun onStart() {
    
    
        super.onStart()
    }
}

​ 在Glide的源码中,with函数有众多的重载,这是为了保证确保能监听到各种activity或者fragment或者application。在这些重载中无一例外的以RequestManager为返回值类型,RequestManager是为了专门去请求加载图片的。这些重载中还无一类外的以return getRetriever.get作为返回值。

public static RequestManager with(@NonNull Context context) {
    
    
    return getRetriever(context).get(context);
}

@NonNull
public static RequestManager with(@NonNull Activity activity) {
    
    
    return getRetriever(activity).get(activity);
}


@NonNull
public static RequestManager with(@NonNull FragmentActivity activity) {
    
    
    return getRetriever(activity).get(activity);
}


@NonNull
public static RequestManager with(@NonNull Fragment fragment) {
    
     // androidx Fragment
    return getRetriever(fragment.getContext()).get(fragment);
}


@SuppressWarnings("deprecation")
@Deprecated
@NonNull
public static RequestManager with(@NonNull android.app.Fragment fragment) {
    
     // app.Fragment
    return getRetriever(fragment.getActivity()).get(fragment);
}

RequestManagerRetriever()

private static RequestManagerRetriever getRetriever(@Nullable Context context) {
    
    
    return Glide.get(context).getRequestManagerRetriever();
}

​ Glide用于监听所属activity/fragment的隐形fragment在getRetriever.get中产生,以Glide的with参数传入类型为Activity为例,其返回 return getRetriever(activity).get(activity);中的get方法如下所示:

public RequestManager get(@NonNull Activity activity) {
    
    
    if (Util.isOnBackgroundThread()) {
    
    
        return get(activity.getApplicationContext());
    } else {
    
    
        Util.assertNotDestroyed(activity);
        android.app.FragmentManager fm = activity.getFragmentManager();  // 在这里产生了 用于管理隐形fragment的管理器
        return fragmentGet(activity, fm);// 在这里产生了 用于监听的隐形activity
    }
}

​ 但是需要注意的是,因为Glide的with参数可以把Context作为参数,所以可以把Application作为参数,但是在这种情况下,Glide将不会生成用于监听的fragment,这种情况的get方法如下:

public RequestManager get(@NonNull Context context) {
    
    
    if (context == null) {
    
    
        throw new IllegalArgumentException("你个货,传入的是 空的 context,要把你吊起来打...");
    } else if (Util.isOnMainThread() && !(context instanceof Application)) {
    
    
        if (context instanceof FragmentActivity) {
    
    
            return get((FragmentActivity) context); // 进入FragmentActivity的get函数
        } else if (context instanceof Activity) {
    
    
            return get((Activity) context); // 进入Activity的get函数
        } else if (context instanceof ContextWrapper && ((ContextWrapper) context).getBaseContext().getApplicationContext() != null) {
    
    
            return get(((ContextWrapper) context).getBaseContext()); // 继续递归寻找 匹配合适的
        }
    }

    // 若上面的判断都不满足,即context为一个application
    return getApplicationManager(context);
}

​ 在getApplicationManager中没有生成隐形fragment。

private RequestManager getApplicationManager(@NonNull Context context) {
    if (applicationManager == null) {
        synchronized (this) {
            if (applicationManager == null) {

                Glide glide = Glide.get(context.getApplicationContext());
                applicationManager = new RequestManager(glide, new ApplicationLifecycle(), context.getApplicationContext());
            }
        }
    }
    return applicationManager;
}

​ 还需要注意的是,当Glide的with函数在一个子线程中执行时,也不会生成隐形fragment。举例:如下代码,当检查出来在子线程时,将会把application作为context传给get,根据上面的分析,Glide将不会生成用于监听的fragment。

public RequestManager get(@NonNull Fragment fragment) {
    
     // androidx
    if (Util.isOnBackgroundThread()) {
    
      //检查如果是在非主线程,则会调用get的参数类型为context的重载。
        return get(fragment.getContext().getApplicationContext());
    } else {
    
    
        FragmentManager fm = fragment.getChildFragmentManager();
        return supportFragmentGet(fragment.getContext(), fm);
    }
}

到这里可以做一个简单的总结,当with的参数类型为fragment,activity(也可以包括view)时,将会生成用于监听的fragment,当with的参数类型为application,或者with在子线程中被使用,将不会生成用于监听的fragment。

​ 上文中指出来了用于监听的隐形fragment,它的具体生成如下:

private RequestManager supportFragmentGet(
        @NonNull Context context,
        @NonNull FragmentManager fm) {
    
    

    // 1、从 FragmentManager 中获取 SupportRequestManagerFragment(隐形)
    SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm);

    // 2、从该 空白Fragment 中获取 RequestManager
    RequestManager requestManager = current.getRequestManager();

    // 3、首次获取,则实例化 RequestManager
    if (requestManager == null) {
    
     // 这样做的目的是为了  一个Activity或Fragment 只能有一个 RequestManager】

        // 3.1 实例化
        Glide glide = Glide.get(context);
        requestManager = new RequestManager(glide, current.getGlideLifecycle(), context);

        // 3.2 设置 Fragment 对应的 RequestManager    空白的Fragment<--->requestManager
        current.setRequestManager(requestManager);
    }
    return requestManager;
}

在上面代码中 在注释1处拿到了监控该fragment隐形fragment,注重分析这个步骤: SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm);

// 1、从 FragmentManager 中获取 RequestManagerFragment
private RequestManagerFragment getRequestManagerFragment(
        @NonNull final android.app.FragmentManager fm) {
    
    

    // 第二次:就不会为null
    // 1.1 尝试获取 FRAGMENT_TAG 对应的 Fragment
    RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);

    if (current == null) {
    
     // 这样做的目的是为了  一个Activity或Fragment 只能有一个 空白的Fragment 对应】

        // 1.2 尝试从【记录保存】中获取 Fragment
        current = pendingRequestManagerFragments.get(fm);

        // 1.3 实例化 Fragment
        if (current == null) {
    
    

            // 1.3.1 创建对象 空白的Fragment
            current = new RequestManagerFragment();

            // 1.3.2 【记录保存】映射关系 进行保存
            pendingRequestManagerFragments.put(fm, current);

            // 1.3.3 提交 Fragment 事务    同学们说:commitNow会抛出异常
            fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();

            // 1.3.4 post 一个消息
            handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
        }
    }
    return current;
}

​ 以上代码有一个重要的作用,就是当在一个activity或者fragment中多次调用Glide.with()方法时,该actiivity/fragment值会生成一个用于监听的隐形fragment,而一个隐形fragment对应一个RequestManager,这样的话 一个被监听的activity/fragment对应一个RequestManager。在上面你的代码中这种唯一的关系的第一个保证是通过map来保证,第二个是通过handler机制(我不理解). 再补充一点,在保存隐形fragment的map中,key为被监听activity/fragment 的fragmentmanager,value为 保存的就时用于监听的隐形fragment。

是为什么说SupportRequestManagerFragment是个隐形的fragment呢?如下:首先因为它继承自Fragment,所以它是个fragment,其次它除了相关的生命周期函数,没有视图,没有其他的,所以说它是隐形的。

// andrid x  隐形的Fragment  监听生命周期变化的
public class SupportRequestManagerFragment extends Fragment {
    
    

    private static final String TAG = "SupportRMFragment";
    private final ActivityFragmentLifecycle lifecycle;
    @Nullable private RequestManager requestManager;

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

    @VisibleForTesting
    @SuppressLint("ValidFragment")
    public SupportRequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
    
    
        this.lifecycle = lifecycle;
    }

    public void setRequestManager(@Nullable RequestManager requestManager) {
    
    
        this.requestManager = requestManager;
    }

    @NonNull
    public ActivityFragmentLifecycle getGlideLifecycle() {
    
    
        return lifecycle;
    }

    @Nullable
    public RequestManager getRequestManager() {
    
    
        return requestManager;
    }
	
    // 相关生命周期函数
    @Override
    public void onAttach(@NonNull Context context) {
    
    
        super.onAttach(context);
        // this.lifecycle.addListener(requestManager);
    }

    @Override
    public void onDetach() {
    
    
        super.onDetach();
    }

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

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

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

​ 在上面代码中,可以注意到的是 在onStart,onStop ,onDestroy方法中调用了lifecycle的相关方法,lifecycle是个接口,如下:接口中有两个方法,分别是添加监听和移除监听。

public interface Lifecycle {
    
    

    void addListener(@NonNull LifecycleListener listener);

    void removeListener(@NonNull LifecycleListener listener);

}

​ 接口Lifecycle有两个实现类,分别是 ActivityFragmentLifecycle,ApplicationLifecycle,这其实分别对应了前文所说的是否生成隐形fragment的两种情况。

// 非Applicatoin作用域 绿色色领域  只有他有资格 搞一个隱形的Fragment来监听
public 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(@NonNull LifecycleListener listener) {
    
    
        lifecycleListeners.add(listener);

        if (isDestroyed) {
    
    
            listener.onDestroy();
        } else if (isStarted) {
    
    
            listener.onStart();
        } else {
    
    
            listener.onStop();  // 首次启动:会默认 onStop 先停止   然后再onStart
        }
    }

    @Override
    public void removeListener(@NonNull LifecycleListener listener) {
    
    
        lifecycleListeners.remove(listener);
    }

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

    void onStop() {
    
    
        isStarted = false;
        for (LifecycleListener lifecycleListener : lifecycleListeners) {
    
    
            lifecycleListener.onStop();
        }
    }

    void onDestroy() {
    
    
        isDestroyed = true;
        for (LifecycleListener lifecycleListener : lifecycleListeners) {
    
    
            lifecycleListener.onDestroy();
        }
    }
}
// Applicatoin作用域 红色领域
public class ApplicationLifecycle implements Lifecycle {
    
    

    @Override
    public void addListener(@NonNull LifecycleListener listener) {
    
    
        /**
         * APP起来了,APP起来的时候,执行onStart
         */
        /**
         * 子线程中,在实例化 RequestManager的时候,会执行 this.lifecycle.addListener(this);
         * 此时,由于是子线程,无法搞一个空白的Fragment覆盖上去,也意味着无法监听 Activity/Fragment
         * 所以 只能是在addListener时,手动的onStart了
         */
        listener.onStart();
    }

    @Override
    public void removeListener(@NonNull LifecycleListener listener) {
    
    
        // 我也没法做事情,APP死亡  我就跟随

        // Do nothing.

        /**
         * 子线程中,由于无法搞一个空白的Fragment覆盖上去,也意味着无法监听 Activity/Fragment
         *  那么只能是属于 全局大范围的跟随App进程的灭亡,而灭亡了,所以啥事也不干了...
         */
    }
}

`

在ApplicationLifecycle 和 ActivityFragmentLifecycle中众多方法中 有一个重要的参数 LifecycleListener ,LifecycleListener是一个接口:如下,可以看到在这个接口中有我们熟悉的onStart,onStop,onDestroy这些方法,

public interface LifecycleListener {
    
    


    void onStart();


    void onStop();


    void onDestroy();

}

RequestManager实现了这个接口: 下面 只是主线机制

public class RequestManager implements LifecycleListener {
    
    

    private Lifecycle lifecycle;

    public RequestManager(Glide glide, Lifecycle lifecycle, Context applicationContext) {
    
    
        this.lifecycle = lifecycle;

        this.lifecycle.addListener(this); // 构造函数 已经给自己注册了【自己给自己绑定】
    }

    // Activity/Fragment 可见时恢复请求 (onStart() ) 掉用函数
    @Override
    public void onStart() {
    
    
        ....
        Log.d(LOG.TAG, "开始执行生命周期业务 onStart: 运行队列 全部执行,等待队列 全部清空 ....");
        ....
    }

    // Activity/Fragment 不可见时暂停请求 (onStop() ) 掉用函数
    @Override
    public void onStop() {
    
    
        ....
        Log.d(LOG.TAG, "开始执行生命周期业务 onStop: 运行队列 全部停止,把任务都加入到等待队列 ....");
        .....
    }

    @Override
    public void onDestroy() {
    
    
        Log.d(LOG.TAG, "开始执行生命周期业务 onDestroy: 自己负责移除自己绑定的生命周期监听,释放操作 ....");
        this.lifecycle.removeListener(this); // 已经给自己销毁了 【自己给自己移除】
    }
}

以ActivityFragmentLifecycle 为例 他们的关系可以用下图描述: 可以观察到的是ActivityFragmentLifecycle 的作用范围往往是 一个fragment或者activity的一个生命周期

在这里插入图片描述

而ApplicationLifecycle和上面的流程类似 ,比不过相比于ActivityFragmentLifecycle ,ApplicationLifecycle的作用范围则是 整个应用的生命周期。

public class ApplicationLifecycle implements Lifecycle {
    
    

    @Override
    public void addListener(@NonNull LifecycleListener listener) {
    
    
        /**
         * APP起来了,APP起来的时候,执行onStart
         */
        /**
         * 子线程中,在实例化 RequestManager的时候,会执行 this.lifecycle.addListener(this);
         * 此时,由于是子线程,无法搞一个空白的Fragment覆盖上去,也意味着无法监听 Activity/Fragment
         * 所以 只能是在addListener时,手动的onStart了
         */
        listener.onStart();
    }

    @Override
    public void removeListener(@NonNull LifecycleListener listener) {
    
    
        // 我也没法做事情,APP死亡  我就跟随

        // Do nothing.

        /**
         * 子线程中,由于无法搞一个空白的Fragment覆盖上去,也意味着无法监听 Activity/Fragment
         *  那么只能是属于 全局大范围的跟随App进程的灭亡,而灭亡了,所以啥事也不干了...
         */
    }
}

总结一下当前遇到的几个核心类:

几个核心类介绍

通过对Glide生命周期绑定和传递整个流程过了一遍之后,大家应该对整体实现的框架有一定的了解。现在再来看下面一些核心类的介绍,应该更加有感触。

  • Glide:库提供对外调用方法的类,传入页面引用。
  • RequestManagerRetriever:一个处理中间类,获取RequestManager和RequestManagerFragment,并将两者绑定
  • RequestManagerFragment:无UI的fragment,与RequestManager绑定,感知并传递页面的生命周期
  • RequestManager:实现了LifeCycleListener,主要作用为结合Activity或Fragment生命周期,对Request进行管理,如pauseRequests(), resumeRequests(), clearRequests()。
  • LifecycleListener:接口,定义生命周期管理方法,onStart(), onStop(), onDestroy(). RequestManager实现了它。
  • ActivityFragmentLifecycle:保存fragment和Requestmanager映射关系的类,管理LifecycleListener, 空白Fragment会回调它的onStart(), onStop(), onDestroy()。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l4gVzxS2-在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_41095045/article/details/123699156
今日推荐