美文网首页
一、【源码分析】Glide生命周期

一、【源码分析】Glide生命周期

作者: ChiangCMBA | 来源:发表于2018-06-14 17:59 被阅读0次

    当Glide.with(android.app.Fragment 或 android.app.Activity 或 android.support.v4.app.FragmentActivity 或 android.support.v4.app.Fragment)时,Glide会添加一个(A view-less)RequestManagerFragment或SupportRequestManagerFragment到视图结构中。以绑定Fragment或者Activity的生命周期,并通过ActivityFragmentLifecycle进行相应生命周期方法的回调。RequestManager implements LifecycleListener接口,通过观察者模式,注册到ActivityFragmentLifecycle中。

    Step1:RequestManager#with(Activity activity)

    /**
         * Begin a load with Glide that will be tied to the given {@link android.app.Activity}'s lifecycle and that uses the
         * given {@link Activity}'s default options.
         *
         * @param activity The activity to use.
         * @return A RequestManager for the given activity that can be used to start a load.
         */
        public static RequestManager with(Activity activity) {
            RequestManagerRetriever retriever = RequestManagerRetriever.get();
            return retriever.get(activity);
        }
    
    

    Step2:RequestManagerRetriever #get(Activity 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(activity, fm);
            }
        }
    
     /**
         * Returns {@code true} if called on the main thread, {@code false} otherwise.
         */
        public static boolean isOnBackgroundThread() {
            return !isOnMainThread();
        }
    
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
        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);
            }
        }
    

    注意get(Activity activity)和get(Fragment fragment) 方法中fragmentGet(fragmentGet(Context context, FragmentManager fm)方法参数FragmentManager的区别。前者是: activity.getFragmentManager();后者是: fragment.getChildFragmentManager();

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

    说明:如果不是在主线程中,或者context是Application的实例对象,则Glide的生命周期最终跟Application的生命周期绑定。

    Step3:RequestManagerRetriever #fragmentGet(Context context, FragmentManager fm)

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
        RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {
            RequestManagerFragment current = getRequestManagerFragment(fm);
            RequestManager requestManager = current.getRequestManager();
            if (requestManager == null) {
                requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
                current.setRequestManager(requestManager);
            }
            return requestManager;
        }
    

    Step4:RequestManagerRetriever#getRequestManagerFragment(final android.app.FragmentManager fm)

    创建一个Fragment,并添加到Activity或者Fragment中。

     @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
        RequestManagerFragment getRequestManagerFragment(final android.app.FragmentManager fm) {
            RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
            if (current == null) {
                current = pendingRequestManagerFragments.get(fm);
                if (current == null) {
                    current = new RequestManagerFragment();
                    pendingRequestManagerFragments.put(fm, current);
                    fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
                    handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
                }
            }
            return current;
        }
    

    关于RequestManagerFragment

    public class RequestManagerFragment extends Fragment {
        private final ActivityFragmentLifecycle lifecycle;
    
        private RequestManager requestManager;
    
        public RequestManagerFragment() {
            this(new ActivityFragmentLifecycle());
        }
    
        // For testing only.
        @SuppressLint("ValidFragment")
        RequestManagerFragment(ActivityFragmentLifecycle lifecycle) {
            this.lifecycle = lifecycle;
        }
    
        ActivityFragmentLifecycle getLifecycle() {
            return lifecycle;
        }
     
        @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 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;
            }
        }
    
    }
    
    

    关于ActivityFragmentLifecycle

    
    /**
     * 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<LifecycleListener, Boolean>());
        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();
            }
        }
    }
    
    

    Step5:RequestManager#RequestManager(Context context, Lifecycle lifecycle, RequestManagerTreeNode treeNode)

    public class RequestManager implements LifecycleListener {
        private final Context context;
        private final Lifecycle lifecycle;
        private final RequestManagerTreeNode treeNode;
        private final RequestTracker requestTracker;
        private final Glide glide;
        private final OptionsApplier optionsApplier;
        private DefaultOptions options;
    
        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 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 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();
        }
    
    /**
         * Restarts any loads that have not yet completed.
         *
         * @see #isPaused()
         * @see #pauseRequests()
         */
        public void resumeRequests() {
            Util.assertMainThread();
            requestTracker.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();
        }
    
    /**
         * Cancels any in progress loads, but does not clear resources of completed loads.
         *
         * @see #isPaused()
         * @see #resumeRequests()
         */
        public void pauseRequests() {
            Util.assertMainThread();
            requestTracker.pauseRequests();
        }
    
        /**
         * Lifecycle callback that cancels all in progress requests and clears and recycles resources for all completed
         * requests.
         */
        @Override
        public void onDestroy() {
            requestTracker.clearRequests();
        }
    
    
    
    

    RequestTracker

    /**
     * A class for tracking, canceling, and restarting in progress, completed, and failed requests.
     */
    public class RequestTracker {
        // Most requests will be for views and will therefore be held strongly (and safely) by the view via the tag.
        // However, a user can always pass in a different type of target which may end up not being strongly referenced even
        // though the user still would like the request to finish. Weak references are therefore only really functional in
        // this context for view targets. Despite the side affects, WeakReferences are still essentially required. A user
        // can always make repeated requests into targets other than views, or use an activity manager in a fragment pager
        // where holding strong references would steadily leak bitmaps and/or views.
        private final Set<Request> requests = Collections.newSetFromMap(new WeakHashMap<Request, Boolean>());
        // A set of requests that have not completed and are queued to be run again. We use this list to maintain hard
        // references to these requests to ensure that they are not garbage collected before they start running or
        // while they are paused. See #346.
        @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
        private final List<Request> pendingRequests = new ArrayList<Request>();
    
        private boolean isPaused;
    
        /**
         * Starts tracking the given request.
         */
        public void runRequest(Request request) {
            requests.add(request);
            if (!isPaused) {
                request.begin();
            } else {
                pendingRequests.add(request);
            }
        }
    
        // Visible for testing.
        void addRequest(Request request) {
            requests.add(request);
        }
    
        /**
         * Stops tracking the given request.
         */
        public void removeRequest(Request request) {
            requests.remove(request);
            pendingRequests.remove(request);
        }
    
        /**
         * Returns {@code true} if requests are currently paused, and {@code false} otherwise.
         */
        public boolean isPaused() {
            return isPaused;
        }
    
        /**
         * Stops any in progress requests.
         */
        public void pauseRequests() {
            isPaused = true;
            for (Request request : Util.getSnapshot(requests)) {
                if (request.isRunning()) {
                    request.pause();
                    pendingRequests.add(request);
                }
            }
        }
    
        /**
         * Starts any not yet completed or failed requests.
         */
        public void resumeRequests() {
            isPaused = false;
            for (Request request : Util.getSnapshot(requests)) {
                if (!request.isComplete() && !request.isCancelled() && !request.isRunning()) {
                    request.begin();
                }
            }
            pendingRequests.clear();
        }
    
        /**
         * Cancels all requests and clears their resources.
         */
        public void clearRequests() {
            for (Request request : Util.getSnapshot(requests)) {
                request.clear();
            }
            pendingRequests.clear();
        }
    
        /**
         * Restarts failed requests and cancels and restarts in progress requests.
         */
        public void restartRequests() {
            for (Request request : Util.getSnapshot(requests)) {
                if (!request.isComplete() && !request.isCancelled()) {
                    // Ensure the request will be restarted in onResume.
                    request.pause();
                    if (!isPaused) {
                        request.begin();
                    } else {
                        pendingRequests.add(request);
                    }
                }
            }
        }
    }
    
    

    图片加载请求绑定生命周期的过程(?)

    以RequestManager#from(Class<T> modelClass)方法创建,图片加载请求过程为参考:

    public <T> DrawableTypeRequest<T> from(Class<T> modelClass) {
            return loadGeneric(modelClass);
        }
    
        private <T> DrawableTypeRequest<T> loadGeneric(Class<T> modelClass) {
          ......//省略部分非核心代码
    
            return optionsApplier.apply(
                    new DrawableTypeRequest<T>(modelClass, streamModelLoader, fileDescriptorModelLoader, context,
                            glide, requestTracker, lifecycle, optionsApplier));
        }
    

    DrawableTypeRequest

    DrawableTypeRequest(Class<ModelType> modelClass, ModelLoader<ModelType, InputStream> streamModelLoader,
                ModelLoader<ModelType, ParcelFileDescriptor> fileDescriptorModelLoader, Context context, Glide glide,
                RequestTracker requestTracker, Lifecycle lifecycle, RequestManager.OptionsApplier optionsApplier) {
            super(context, modelClass,
                    buildProvider(glide, streamModelLoader, fileDescriptorModelLoader, GifBitmapWrapper.class,
                            GlideDrawable.class, null),
                    glide, requestTracker, lifecycle);
            this.streamModelLoader = streamModelLoader;
            this.fileDescriptorModelLoader = fileDescriptorModelLoader;
            this.optionsApplier = optionsApplier;
        }
    

    DrawableRequestBuilder

     DrawableRequestBuilder(Context context, Class<ModelType> modelClass,
                LoadProvider<ModelType, ImageVideoWrapper, GifBitmapWrapper, GlideDrawable> loadProvider, Glide glide,
                RequestTracker requestTracker, Lifecycle lifecycle) {
            super(context, modelClass, loadProvider, GlideDrawable.class, glide, requestTracker, lifecycle);
            // Default to animating.
            crossFade();
        }
    

    GenericRequestBuilder

    GenericRequestBuilder(Context context, Class<ModelType> modelClass,
                LoadProvider<ModelType, DataType, ResourceType, TranscodeType> loadProvider,
                Class<TranscodeType> transcodeClass, Glide glide, RequestTracker requestTracker, Lifecycle lifecycle) {
            this.context = context;
            this.modelClass = modelClass;
            this.transcodeClass = transcodeClass;
            this.glide = glide;
            this.requestTracker = requestTracker;
            this.lifecycle = lifecycle;
            this.loadProvider = loadProvider != null
                    ? new ChildLoadProvider<ModelType, DataType, ResourceType, TranscodeType>(loadProvider) : null;
    
            if (context == null) {
                throw new NullPointerException("Context can't be null");
            }
            if (modelClass != null && loadProvider == null) {
                throw new NullPointerException("LoadProvider must not be null");
            }
        }
    

    GenericRequestBuilder#into(Y target)

    lifecycle.addListener(target);将target作为观察者注册到lifecycle(被观察者)。

    public <Y extends Target<TranscodeType>> Y into(Y target) {
            Util.assertMainThread();
            if (target == null) {
                throw new IllegalArgumentException("You must pass in a non null Target");
            }
            if (!isModelSet) {
                throw new IllegalArgumentException("You must first set a model (try #load())");
            }
    
            Request previous = target.getRequest();
    
            if (previous != null) {
                previous.clear();
                requestTracker.removeRequest(previous);
                previous.recycle();
            }
    
            Request request = buildRequest(target);
            target.setRequest(request);
            lifecycle.addListener(target);
            requestTracker.runRequest(request);
    
            return target;
        }
    

    Target和LifecycleListener

    public interface Target<R> extends LifecycleListener {}
    
    /**
     * 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();
    }
    

    相关文章

      网友评论

          本文标题:一、【源码分析】Glide生命周期

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