Glide源码之生命周期

glide是怎么和activity、fragment绑定声明周期的呢?


咱们使用glide样例
        RequestManager requestManager = Glide.with(mContext);
        requestManager.load(url)
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .listener(new LoggingListener())
                .fitCenter()
                .error(mContext.getResources().getDrawable(R.drawable.xxx_icon))
                .placeholder(mContext.getResources().getDrawable(R.drawable.xxx_icon))
                .crossFade(200)
                .transform(new GlideRoundTransform(mContext))
                .into(image);

从最开始的Glide.with(mContext) 开始。
链接进去之后是这样(我的源码是glide 3.7)
/**
 * Begin a load with Glide by passing in a context.
 *
 * <p>
 *     Any requests started using a context will only have the application level options applied and will not be
 *     started or stopped based on lifecycle events. In general, loads should be started at the level the result
 *     will be used in. If the resource will be used in a view in a child fragment,
 *     the load should be started with {@link #with(android.app.Fragment)}} using that child fragment. Similarly,
 *     if the resource will be used in a view in the parent fragment, the load should be started with
 *     {@link #with(android.app.Fragment)} using the parent fragment. In the same vein, if the resource will be used
 *     in a view in an activity, the load should be started with {@link #with(android.app.Activity)}}.
 * </p>
 *
 * <p>
 *     This method is appropriate for resources that will be used outside of the normal fragment or activity
 *     lifecycle (For example in services, or for notification thumbnails).
 * </p>
 *
 * @see #with(android.app.Activity)
 * @see #with(android.app.Fragment)
 * @see #with(android.support.v4.app.Fragment)
 * @see #with(android.support.v4.app.FragmentActivity)
 *
 * @param context Any context, will not be retained.
 * @return A RequestManager for the top level application that can be used to start a load.
 */
public static RequestManager with(Context context) {
    RequestManagerRetriever retriever = RequestManagerRetriever.get();
    return retriever.get(context);
}

这个类注释大概意思是
通过context加载glide
每一个请求都有生命周期,生命周期跟这个要显示的view的容器有关,就时fragment或者activity,这里支持app包和v4包中的Fragment和Activity
context 是不会被glide给保存的,这个可以后续看下是用了什么方式,其实是用了context.getApplicationContext,实际使用了application 的context
然后看看这个方法中的主要元素
RequestManagerRetriever 
/**
 * A collection of static methods for creating new {@link com.bumptech.glide.RequestManager}s or retrieving existing
 * ones from activities and fragment.
 */
public class RequestManagerRetriever implements Handler.Callback {

创建RequestManager 和保存已经存在的activities和fragment的类,
下面是他的get方法,其实是返回一个实例
/**
 * Retrieves and returns the RequestManagerRetriever singleton.
 */
public static RequestManagerRetriever get() {
    return INSTANCE;
}
/** The singleton instance of RequestManagerRetriever. */
private static final RequestManagerRetriever INSTANCE = new RequestManagerRetriever();

实例是new出来的
然后继续看代码,这个类的get方法
public RequestManager get(Context context) {
    if (context == null) {
        throw new IllegalArgumentException("You cannot start a load on a null Context");
    else if (Util.isOnMainThread() && !(context instanceof Application)) {
        if (context instanceof FragmentActivity) {
            return get((FragmentActivity) context);
        else if (context instanceof Activity) {
            return get((Activity) context);
        else if (context instanceof ContextWrapper) {
            return get(((ContextWrapper) context).getBaseContext());
        }
    }

    return getApplicationManager(context);
}
就是最开始调用的
public static RequestManager with(Context context) {
    RequestManagerRetriever retriever = RequestManagerRetriever.get();
    return retriever.get(context);
}
中的get方法
用instanceof方法判断是FragmentActivity、Activity还是ContextWrapper,其实最后的ContextWrapper还是调用的自己,只是把参数类型转换成了Application类型的context了
这里其实处理了三种类型,FragmentActivity、Activity、Applicationn
先来看FramentActivity为参数的
public RequestManager get(FragmentActivity activity) {
    if (Util.isOnBackgroundThread()) {
        return get(activity.getApplicationContext());
    else {
        assertNotDestroyed(activity);
        FragmentManager fm = activity.getSupportFragmentManager();
        return supportFragmentGet(activityfm);
    }
}
如果不是在UI线程的话,就说明没有生命周期,就调用了Application的get方法
如果在UI线程中,判断是否销毁了这个Activity。然后执行
RequestManager supportFragmentGet(Context contextFragmentManager fm) {
    SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm);
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
        requestManager = new RequestManager(contextcurrent.getLifecycle()current.getRequestManagerTreeNode());
        current.setRequestManager(requestManager);
    }
    return requestManager;
}

先看第一行代码,进入了另外一个方法
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(fmcurrent);
            fm.beginTransaction().add(currentFRAGMENT_TAG).commitAllowingStateLoss();
            handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGERfm).sendToTarget();
        }
    }
    return current;
}

这个类说明了是如何将绑定FragmentActivity声明周期的方法了
就是在activity中加入一个不可见的Fragment,这样随着这个Activity的生命周期改变,内部的Fragment也会改变,就可以处理图片加载的生命周期了
这里的current就是这个fragment,用了pendingSupportRequestManagerFragments来保存起来,这个key是FragmentManager
这里的第一步先从FragmentManager中找这个activity是否已经创建了这个glide的生命周期的Fragment。如果没创建才从pendingSupportRequestManagerFragments这个里头找
/** Pending adds for SupportRequestManagerFragments. */
final Map<FragmentManagerSupportRequestManagerFragment> pendingSupportRequestManagerFragments =
        new HashMap<FragmentManagerSupportRequestManagerFragment>();
这个其实就是一个HashMap,
在commit成功之后,就发送了一个handler讲这个fm从pendingSupportRequestManagerFragments移除了,这个其实是在commit过程中会有延迟,在同一个activity中会加载多个图片,多次执行这个方法
这个HashMap只是作为缓冲使用的一种方式,加入成功之后,就把数据清空了,以防止引用Activity,到时内存泄漏。
这个方式可以学习借鉴一下。用FragmentManager 的TAG自己存储,用handler协助处理。那个commitAllowingStateLoss()方式其实和commit方法差不多,只是为了方式Fragment状态丢失发生错误的兼容。
然后回到上一个方法
RequestManager supportFragmentGet(Context contextFragmentManager fm) {
    SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm);
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
        requestManager = new RequestManager(contextcurrent.getLifecycle()current.getRequestManagerTreeNode());
        current.setRequestManager(requestManager);
    }
    return requestManager;
}

SupportRequestManagerFragment这个类就是集成Fragment,然后支持RequestManger的类,然后看一下代码:
/**
 * A view-less {@link android.support.v4.app.Fragment} used to safely store an
 * {@link com.bumptech.glide.RequestManager} that can be used to start, stop and manage Glide requests started for
 * targets within the fragment or activity this fragment is a child of.
 *
 * @see com.bumptech.glide.manager.RequestManagerFragment
 * @see com.bumptech.glide.manager.RequestManagerRetriever
 * @see com.bumptech.glide.RequestManager
 */
public class SupportRequestManagerFragment extends Fragment {

这个类里重写了onAttch()、onDetach()、onStart()、onStop()、onDestory()方法
@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;
    }
}

@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 an activity is re-created, onLowMemory may be called before a manager is ever set.
    // See #329.
    if (requestManager != null) {
        requestManager.onLowMemory();
    }
}
再回到那个方法

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

之后的RequestManager第一次进来是null的,然后new一个,里边就绑定了相关的声明周期的方法,

再看看Fragment是如何处理生命周期的
public RequestManager get(Fragment fragment) {
    if (fragment.getActivity() == null) {
        throw new IllegalArgumentException("You cannot start a load on a fragment before it is attached");
    }
    if (Util.isOnBackgroundThread()) {
        return get(fragment.getActivity().getApplicationContext());
    else {
        FragmentManager fm = fragment.getChildFragmentManager();
        return supportFragmentGet(fragment.getActivity()fm);
    }
}

使用它的ChildFragmentManager()方法的

再看看app包下的Activity
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
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(activityfm);
    }
}

还有一个Application的context处理方式
private RequestManager getApplicationManager(Context context) {
    // Either an application context or we're on a background thread.
    if (applicationManager == null) {
        synchronized (this) {
            if (applicationManager == null) {
                // Normally pause/resume is taken care of by the fragment we add to the fragment or activity.
                // However, in this case since the manager attached to the application will not receive lifecycle
                // events, we must force the manager to start resumed using ApplicationLifecycle.
                applicationManager new RequestManager(context.getApplicationContext(),
                        new ApplicationLifecycle(), new EmptyRequestManagerTreeNode());
            }
        }
    }

    return applicationManager;
}

如果存在就直接返回了,如果第一次进来,就new ApplicationLifecycle()这个lifecycle类
package com.bumptech.glide.manager;

/**
 * A {@link com.bumptech.glide.manager.Lifecycle} implementation for tracking and notifying listeners of
 * {@link android.app.Application} lifecycle events.
 *
 * <p>
 *     Since there are essentially no {@link android.app.Application} lifecycle events, this class simply defaults to
 *     notifying new listeners that they are started.
 * </p>
 */
class ApplicationLifecycle implements Lifecycle {
    @Override
    public void addListener(LifecycleListener listener) {
        listener.onStart();
    }
}

源码是这样的,就是直接开始了,就没有周期的概念了。这事在子线程或者找不到是从哪里来的情况下使用的默认生命周期方式。

对应的不是默认的生命周期处理方法
package com.bumptech.glide.manager;

import com.bumptech.glide.util.Util;

import java.util.Collections;
import java.util.Set;
import java.util.WeakHashMap;

/**
 * A {@link com.bumptech.glide.manager.Lifecycle} implementation for tracking and notifying listeners of
 * {@link android.app.Fragment} and {@link android.app.Activity} lifecycle events.
 */
class ActivityFragmentLifecycle implements Lifecycle {
    private final Set<LifecycleListener> lifecycleListeners =
            Collections.newSetFromMap(new WeakHashMap<LifecycleListenerBoolean>());
    private boolean isStarted;
    private boolean isDestroyed;

    /**
     * Adds the given listener to the list of listeners to be notified on each lifecycle event.
     *
     * <p>
     *     The latest lifecycle event will be called on the given listener synchronously in this method. If the
     *     activity or fragment is stopped, {@link LifecycleListener#onStop()}} will be called, and same for onStart and
     *     onDestroy.
     * </p>
     *
     * <p>
     *     Note - {@link com.bumptech.glide.manager.LifecycleListener}s that are added more than once will have their
     *     lifecycle methods called more than once. It is the caller's responsibility to avoid adding listeners
     *     multiple times.
     * </p>
     */
    @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();
        }
    }
}

这个类里处理了存在多个lister的方法,主要关键是是否distory和是否start,
再看看这个lifecycyleListener源码
package com.bumptech.glide.manager;

/**
 * An interface for listener to {@link android.app.Fragment} and {@link android.app.Activity} lifecycle events.
 */
public interface LifecycleListener {

    /**
     * Callback for when {@link android.app.Fragment#onStart()}} or {@link android.app.Activity#onStart()} is called.
     */
    void onStart();

    /**
     * Callback for when {@link android.app.Fragment#onStop()}} or {@link android.app.Activity#onStop()}} is called.
     */
    void onStop();

    /**
     * Callback for when {@link android.app.Fragment#onDestroy()}} or {@link android.app.Activity#onDestroy()} is
     * called.
     */
    void onDestroy();
}

再分析下RequestManager

/**
 * A class for managing and starting requests for Glide. Can use activity, fragment and connectivity lifecycle events to
 * intelligently stop, start, and restart requests. Retrieve either by instantiating a new object, or to take advantage
 * built in Activity and Fragment lifecycle handling, use the static Glide.load methods with your Fragment or Activity.
 *
 * @see Glide#with(android.app.Activity)
 * @see Glide#with(android.support.v4.app.FragmentActivity)
 * @see Glide#with(android.app.Fragment)
 * @see Glide#with(android.support.v4.app.Fragment)
 * @see Glide#with(Context)
 */
public class RequestManager implements LifecycleListener {

在创建他的时候传入了一个Fragment的lifecycle对象
RequestManager supportFragmentGet(Context contextFragmentManager fm) {
    SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm);
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
        requestManager = new RequestManager(contextcurrent.getLifecycle()current.getRequestManagerTreeNode());
        current.setRequestManager(requestManager);
    }
    return requestManager;
}

看看RequestManager的构造方法
RequestManager(Context context, final Lifecycle lifecycleRequestManagerTreeNode treeNode,
        RequestTracker requestTrackerConnectivityMonitorFactory 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 we're the application level request manager, we may be created on a background thread. In that case we
    // cannot risk synchronously pausing or resuming requests, so we hack around the issue by delaying adding
    // ourselves as a lifecycle listener by posting to the main thread. This should be entirely safe.
    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);
}

讲lifecycle.addListener()设置为自己,就是这个RequestManager实现了的LifecycleListener接口

/**
 * Lifecycle callback that registers for connectivity events (if the android.permission.ACCESS_NETWORK_STATE
 * permission is present) and restarts failed or paused requests.
 */
@Override
public void onStart() {
    // onStart might not be called because this object may be created after the fragment/activity's onStart method.
    resumeRequests();
}

/**
 * Lifecycle callback that unregisters for connectivity events (if the android.permission.ACCESS_NETWORK_STATE
 * permission is present) and pauses in progress loads.
 */
@Override
public void onStop() {
    pauseRequests();
}

/**
 * Lifecycle callback that cancels all in progress requests and clears and recycles resources for all completed
 * requests.
 */
@Override
public void onDestroy() {
    requestTracker.clearRequests();
}

这其中有个监听网络变化的接口
package com.bumptech.glide.manager;

/**
 * An interface for monitoring network connectivity events.
 */
public interface ConnectivityMonitor extends LifecycleListener {

    /**
     * An interface for listening to network connectivity events picked up by the monitor.
     */
    interface ConnectivityListener {
        /**
         * Called when the connectivity state changes.
         *
         * @param isConnected True if we're currently connected to a network, false otherwise.
         */
        void onConnectivityChanged(boolean isConnected);
    }
}

他最终是一个动态注册的广播
private final BroadcastReceiver connectivityReceiver new BroadcastReceiver() {
    @Override
    public void onReceive(Context contextIntent intent) {
        boolean wasConnected = isConnected;
        isConnected = isConnected(context);
        if (wasConnected != isConnected) {
            listener.onConnectivityChanged(isConnected);
        }
    }
};

private boolean isConnected(Context context) {
    ConnectivityManager connectivityManager =
            (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
    return networkInfo != null && networkInfo.isConnected();
}

@Override
public void onStart() {
    register();
}

@Override
public void onStop() {
    unregister();
}

@Override
public void onDestroy() {
    // Do nothing.
}     

最后分析下整理流程:
1.判断是Activity、Fragment,Application,用instanceof判断传进来的是哪个context的实现。
2.根据不同的容器,创建不同的子Fragment,不显示出来。
3.根据不同的容器(如Activity)的状态改变,子的Fragemnt就改变了状态,将需要用的生命周期接口提取出来。
4.将生命周期传递到RequestManager中对应不同的状态做相应的生命周期处理。










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

method_chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值