動(dòng)腦學(xué)院Glide預(yù)習(xí)資料 生命周期管理

Glide生命周期管理

本文是Glide源碼解析系列的第一篇,通過這篇文檔躯枢,將可以了解到:

  • 1.Glide如何綁定Activity库糠、Fragment生命周期。
  • 2.Glide如何監(jiān)聽內(nèi)存變化氓奈、網(wǎng)絡(luò)變化。
  • 3.Glide如何處理請(qǐng)求的生命周期鼎天。

1.0 生命周期相關(guān)UML類圖

image

2.0 生命周期綁定

Glide生命周期綁定是從入口單例類Glide開始的舀奶,通過with()多個(gè)重載方法來實(shí)現(xiàn)對(duì)生命周期的綁定工作。

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的參數(shù)為例:

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

RequestManagerRetriever是一個(gè)單例類训措,可以理解為一個(gè)工廠類伪节,通過get方法接收不同的參數(shù),來創(chuàng)建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);
    }
}

如果是在子線程進(jìn)行的with操作怀大,那么Glide將默認(rèn)使用ApplicationContext,可以理解為不對(duì)請(qǐng)求的生命周期進(jìn)行管理呀闻,通過Activity拿到FragmentManager化借,并將創(chuàng)建RequestManager的任務(wù)傳遞下去。最終都走到了fragmentGet方法捡多,注意細(xì)微區(qū)別是Activity傳的參數(shù)的是Activity的FragmentManager蓖康,F(xiàn)ragment傳的參數(shù)的是ChildFragmentManager,這兩者不是一個(gè)東西垒手。

RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {
    //獲取RequestManagerFragment蒜焊,并獲取綁定到這個(gè)fragment的RequestManager
    RequestManagerFragment current = getRequestManagerFragment(fm);
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
    //如果獲取RequestManagerFragment還沒有綁定過RequestManager,那么就創(chuàng)建RequestManager并綁定到RequestManagerFragment
        requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
        current.setRequestManager(requestManager);
    }
    return requestManager;
}

2.0.1 創(chuàng)建RequestManagerFragment

這個(gè)方法創(chuàng)建了一個(gè)fragment科贬,并且創(chuàng)建并綁定了一個(gè)RequestManager泳梆,看看getRequestManagerFragment如何獲取的RequestManagerFragment。

RequestManagerFragment getRequestManagerFragment(final android.app.FragmentManager fm) {
    //嘗試根據(jù)id去找到此前創(chuàng)建的RequestManagerFragment
    RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
        //如果沒有找到榜掌,那么從臨時(shí)存儲(chǔ)中尋找
        current = pendingRequestManagerFragments.get(fm);
        if (current == null) {
            //如果仍然沒有找到优妙,那么新建一個(gè)RequestManagerFragment,并添加到臨時(shí)存儲(chǔ)中憎账。
            //然后開啟事務(wù)綁定fragment并使用handler發(fā)送消息來將臨時(shí)存儲(chǔ)的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;
}

這里有個(gè)問題,為什么需要使用pendingRequestManagerFragments這樣一個(gè)集合來臨時(shí)存儲(chǔ)一下fragment胞皱,然后又馬上通過handler發(fā)送消息移除邪意?這其實(shí)是跟主線程的Looper機(jī)制和Fragment的事務(wù)機(jī)制有關(guān)的。我們知道反砌,android中的主線程是一個(gè)閉環(huán)抄罕,通過Handler發(fā)送消息到MessageQueue,然后通過Looper輪詢獲取消息并交給Handler處理于颖。如下面一個(gè)常見場(chǎng)景:

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

這段代碼通過Glide加載了兩張圖片并設(shè)置到了兩個(gè)ImageView上呆贿,當(dāng)以上代碼塊執(zhí)行時(shí),其所屬的代碼群的Message剛剛從MessageQueue中取出正在被處理森渐,我們假設(shè)這個(gè)Message為m1做入,并且這個(gè)MessageQueue中沒有其他消息。此時(shí)情形是這樣的:

image

當(dāng)代碼執(zhí)行到getRequestManagerFragment這個(gè)方法時(shí)同衣,會(huì)通過開啟事務(wù)的方式來綁定這個(gè)fragment到activity竟块,相關(guān)源碼如下,這個(gè)方法在FragmentManagerImpl.java中:

public void enqueueAction(Runnable action, boolean allowStateLoss) {
    if (!allowStateLoss) {
        checkStateLoss();
    }
    synchronized (this) {
        if (mDestroyed || mHost == null) {
            throw new IllegalStateException("Activity has been destroyed");
        }
        if (mPendingActions == null) {
            mPendingActions = new ArrayList<Runnable>();
        }
        mPendingActions.add(action);
        if (mPendingActions.size() == 1) {
            mHost.getHandler().removeCallbacks(mExecCommit);
            mHost.getHandler().post(mExecCommit);
        }
    }
}

這里的mHost其實(shí)就是activity創(chuàng)建的耐齐,并且持有activity以及mMainHandler的引用浪秘,根據(jù)上述代碼可以知道蒋情,其實(shí)綁定fragment的操作最終是通過主線程的handler發(fā)送消息處理的,我們假設(shè)這個(gè)消息為m2耸携。然后handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();這句代碼發(fā)送的消息為m3棵癣。那么當(dāng)Glide.with(this).load(url_1).into(mImageView_1);這句代碼執(zhí)行這里時(shí),消息隊(duì)列有了變化:

image

但是m2這個(gè)消息并不會(huì)馬上被處理夺衍,這是因?yàn)閙1還有代碼還沒有執(zhí)行完畢隙券,也就是說這個(gè)fragment并不會(huì)馬上被綁定酵紫,此時(shí)m1繼續(xù)向下執(zhí)行到第二句代碼Glide.with(this).load(url_2).into(mImageView_2);當(dāng)這句代碼走到getRequestManagerFragment時(shí)爱葵,如果在m1時(shí)惠啄,我們不將fragment臨時(shí)存儲(chǔ)在pendingRequestManagerFragments中,由于m2還沒有被處理矛紫,那么

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

必然是找不到這個(gè)fragment的赎瞎,那么就會(huì)導(dǎo)致重新創(chuàng)建一個(gè)新的重復(fù)的fragment,并開啟事務(wù)綁定颊咬,這顯然是不合情理的煎娇,因?yàn)镚lide需要保證rootFragment的唯一性,rootFragment即fragment依附或者沒有fragment依附的activity所創(chuàng)建的最上層RequestManagerFragment贪染。
接著往下看RequestManagerFragment的構(gòu)造方法做了什么缓呛。

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

直接創(chuàng)建一個(gè)ActivityFragmentLifecycle,這個(gè)類實(shí)際是一個(gè)生命周期回調(diào)的管理類杭隙,實(shí)現(xiàn)了Lifecycle接口哟绊。所有的LifecycleListener會(huì)添加到一個(gè)集合中,當(dāng)RequestManagerFragment生命周期方法觸發(fā)時(shí)痰憎,會(huì)調(diào)用ActivityFragmentLifecycle相應(yīng)生命周期方法票髓,這個(gè)方法然后再遍歷調(diào)用所有LifecycleListener的生命周期方法,以onStart生命周期方法為例铣耘,RequestManagerFragment中:

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

然后ActivityFragmentLifecycle中:

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

2.0.2 rootRequestManagerFragment

上面UML圖上洽沟,可以知道RequestManagerFragment還有一個(gè)rootRequestManagerFragment的成員變量,Glide每創(chuàng)建一個(gè)RequestManagerFragment蜗细,都會(huì)嘗試實(shí)例化rootRequestManagerFragment裆操,這個(gè)fragment即頂級(jí)的Activity所創(chuàng)建的RequestManagerFragment,相關(guān)代碼:

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

可以看到炉媒,不管當(dāng)前的RequestManagerFragment是通過何種方式創(chuàng)建的踪区,都會(huì)在OnAttach時(shí),拿到當(dāng)前所綁定的Activity的FragmentManager來初始化一個(gè)RequestManagerFragment吊骤,這個(gè)RequestManagerFragment有可能是自身缎岗,有可能已經(jīng)被初始化過了,比如是通過with(Activity activity)的方式初始化的白粉,那么很顯然

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

這句代碼拿到的會(huì)是自己本身传泊,而如果是通過with(Fragment fragment)的形式創(chuàng)建的鼠渺,rootRequestManagerFragment將指向當(dāng)前fragment綁定到Activity所綁定的RequestManagerFragment,如果該Activity沒有綁定過眷细,那么會(huì)開啟事務(wù)綁定一個(gè)RequestManagerFragment拦盹。并且如果自己不是rootRequestManagerFragment的話,那么將會(huì)把自己保存到rootRequestManagerFragment中的一個(gè)集合:

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

簡(jiǎn)而言之薪鹦,Glide會(huì)為Activity創(chuàng)建一個(gè)RequestManagerFragment做為rootFragment掌敬,并保存該Activity底下所有Fragment(如果有的話)所創(chuàng)建的RequestManagerFragment惯豆。

2.0.3 RequestManagerTreeNode

RequestManagerFragment初始化時(shí)池磁,還會(huì)初始化RequestManagerTreeNode,顧名思義楷兽,這個(gè)類是用來保存請(qǐng)求樹節(jié)點(diǎn)的地熄,比如一個(gè)Activity采用Viewpager + Fragment的形式,而里面的Fragment又是一個(gè)ViewPager + Fragment的形式芯杀,這個(gè)時(shí)候端考,假設(shè)其中一個(gè)RequestManagerFragment生命周期方法走了,怎么知道哪些RequestManagerFragment綁定的LifeCycle應(yīng)該得到調(diào)用呢揭厚?理想的情況是却特,應(yīng)該讓綁定該RequestManagerFragment的Fragment所有的子Fragment的RequestManagerFragment的生命周期得到調(diào)用,比如如下場(chǎng)景中筛圆,Activity中各有兩個(gè)Fragment裂明,兩個(gè)Fragment又各有兩個(gè)子Fragment,在所有Fragment中太援,均通過with(this)的方式來加載圖片闽晦,經(jīng)過之前的分析我們可以知道的是,ROOT RMF 中會(huì)保存有6個(gè)RMF(RMF即RequestManagerFragment):

image

當(dāng)如果F1 RMF生命周期做出反應(yīng)時(shí)提岔,因?yàn)镽equestManagerFragment是無界面的仙蛉,所以可以理解為F1的生命周期做出反應(yīng)。我們希望F11和F12所綁定的RequestManagerFragment也要立即做出反應(yīng)碱蒙。但是F2以及其底下的RequestManagerFragment則不應(yīng)響應(yīng)對(duì)應(yīng)生命周期事件荠瘪,我們知道任何一個(gè)RequestManagerFragment可以通過rootRequestManagerFragment拿到這6個(gè)RMF,繼而拿到其所對(duì)應(yīng)的RequestManager赛惩,那么怎么去確定F11 RMF 和 F12 RMF呢巧还?這就是RequestManagerTreeNode干的事情了,RequestManagerFragment中的非靜態(tài)內(nèi)部類FragmentRequestManagerTreeNode實(shí)現(xiàn)了RequestManagerTreeNode:

private class FragmentRequestManagerTreeNode implements RequestManagerTreeNode {
    @Override
    public Set<RequestManager> getDescendants() {
        Set<RequestManagerFragment> descendantFragments = getDescendantRequestManagerFragments();
        HashSet<RequestManager> descendants =
            new HashSet<RequestManager>(descendantFragments.size());
        for (RequestManagerFragment fragment : descendantFragments) {
            if (fragment.getRequestManager() != null) {
                descendants.add(fragment.getRequestManager());
            }
        }
        return descendants;
    }
}

這個(gè)類做的事情比較簡(jiǎn)單坊秸,調(diào)用外部類RequestManagerFragment的方法getDescendantRequestManagerFragments拿到所有的“后裔”Fragment,然后再取出它的RequestManager麸祷,然后集合裝起來返回,這里的后裔在前面的例子中褒搔,指的就是F11 RMF 和 F12 RMF阶牍,看看getDescendantRequestManagerFragments是怎么拿到的F11和F12:

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public Set<RequestManagerFragment> getDescendantRequestManagerFragments() {
    //如果自己是rootFragment喷面,那么直接返回childRequestManagerFragments
    if (rootRequestManagerFragment == this) {
        return Collections.unmodifiableSet(childRequestManagerFragments);
    } else if (rootRequestManagerFragment == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
        // Pre JB MR1 doesn't allow us to get the parent fragment so we can't introspect hierarchy, so just
        // return an empty set.
        return Collections.emptySet();
    } else {
        HashSet<RequestManagerFragment> descendants = new HashSet<RequestManagerFragment>();
        for (RequestManagerFragment fragment
                //遍歷取出rootFragment中的RMF,并獲取到其parentFragment走孽,找出后裔惧辈。
                : rootRequestManagerFragment.getDescendantRequestManagerFragments()) {
            if (isDescendant(fragment.getParentFragment())) {
                descendants.add(fragment);
            }
        }
        return Collections.unmodifiableSet(descendants);
    }
}

看看isDescendant方法是如何判斷的:

private boolean isDescendant(Fragment fragment) {
    Fragment root = this.getParentFragment();
    while (fragment.getParentFragment() != null) {
        if (fragment.getParentFragment() == root) {
            return true;
        }
        fragment = fragment.getParentFragment();
    }
    return false;
}

依上面的例子,當(dāng)遍歷到F11 RMF時(shí)磕瓷,參數(shù)傳遞過來的是F11盒齿,root 則為F1,F(xiàn)11再拿到parent困食,也是F1边翁,返回true,F(xiàn)12 RMF類似也返回true硕盹;
當(dāng)遍歷到F21 RMF時(shí)符匾,參數(shù)傳入F21,root仍是F1瘩例,此時(shí)F21再怎么拿Parent也不可能是root,返回false啊胶。
簡(jiǎn)而言之,RequestManagerTreeNode用來獲取綁定該RequestManagerFragment的Fragment的所有子Fragment所綁定的RequestManagerFragment所綁定的RequestManager

2.0.4 RequestManager

上面一直在說RequestManagerFragment垛贤,下面回到FragmentGet方法中焰坪,再貼一次,免得上翻麻煩:

RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {
    //獲取RequestManagerFragment聘惦,并獲取綁定到這個(gè)fragment的RequestManager
    RequestManagerFragment current = getRequestManagerFragment(fm);
    RequestManager requestManager = current.getRequestManager();
    if (requestManager == null) {
    //如果獲取RequestManagerFragment還沒有綁定過RequestManager某饰,那么就創(chuàng)建RequestManager并綁定到RequestManagerFragment
        requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
        current.setRequestManager(requestManager);
    }
    return requestManager;
}

根據(jù)上面的UML圖,可以知道RequestManager是一個(gè)非常核心的類部凑,并且還實(shí)現(xiàn)了LifecycleListener來處理請(qǐng)求的生命周期露乏。上述代碼在創(chuàng)建RequestManager時(shí),傳遞了3個(gè)參數(shù)涂邀,分別是context瘟仿,前面分析過的初始化RequestManagerFragment所創(chuàng)建的LifeCycle和RequestManagerTreeNode。直接看RequestManager的構(gòu)造函數(shù):

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

調(diào)用的另一個(gè)構(gòu)造方法比勉,并增加了兩個(gè)新的參數(shù)RequestTracker和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);
}

RequestTracker即所有請(qǐng)求操作的真正處理者,所有Request的暫停取消執(zhí)行操作都由RequestTracker來完成浩聋,如RequestManager暫停請(qǐng)求的實(shí)現(xiàn):

public void pauseRequests() {
    Util.assertMainThread();
    requestTracker.pauseRequests();
}

2.0.5 網(wǎng)絡(luò)狀態(tài)監(jiān)測(cè)

請(qǐng)求生命周期的實(shí)現(xiàn)細(xì)節(jié)后面再說观蜗,暫時(shí)埋坑,先來看看ConnectivityMonitorFactory這個(gè)工廠生產(chǎn)了什么衣洁。

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

很簡(jiǎn)單墓捻,接收一個(gè)ConnectivityListener根據(jù)是否有監(jiān)控網(wǎng)絡(luò)狀態(tài)的權(quán)限來創(chuàng)建相應(yīng)的網(wǎng)絡(luò)監(jiān)控器。
DefaultConnectivityMonitor也比較簡(jiǎn)單坊夫,就是內(nèi)部定義了一個(gè)廣播接收者砖第,并且也實(shí)現(xiàn)了lifeCycleListener撤卢。在上面RequestManager的構(gòu)造方法中,創(chuàng)建了一個(gè)RequestManagerConnectivityListener:

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

這個(gè)listener很簡(jiǎn)單梧兼,收到網(wǎng)絡(luò)狀態(tài)連接就重啟請(qǐng)求放吩。然后通過工廠創(chuàng)建出了DefaultConnectivityMonitor,并把它添加到了lifecycle中羽杰。到這里渡紫,Glide監(jiān)測(cè)網(wǎng)絡(luò)狀態(tài)來重啟請(qǐng)求的實(shí)現(xiàn)方式就呼之欲出了,大體步驟如下:
在相應(yīng)的生命周期方法中考赛,會(huì)調(diào)用lifecycle的生命周期方法惕澎,lifecycle會(huì)調(diào)用DefaultConnectivityMonitor所實(shí)現(xiàn)的相應(yīng)生命周期方法來注冊(cè)及解除注冊(cè)網(wǎng)絡(luò)狀態(tài)的廣播接收者,收到廣播后欲虚,會(huì)回調(diào)之前傳遞的參數(shù)ConnectivityListener的onConnectivityChanged方法來處理Request集灌。

2.0.6 內(nèi)存狀態(tài)監(jiān)測(cè)

RequestManager中還存有Glide這個(gè)入口類的實(shí)例悔雹,構(gòu)造方法中直接獲取到的复哆,用來對(duì)內(nèi)存狀態(tài)的變更作出處理,比較簡(jiǎn)單腌零,看看流程便可以了梯找,以onTrimMemory為例,
當(dāng)RequestManagerFragment的onTrimMemory被調(diào)用時(shí),會(huì)調(diào)用其綁定的RequetManager的相應(yīng)方法來處理:

@Override
public void onTrimMemory(int level) {
    // If an activity is re-created, onTrimMemory may be called before a manager is ever set.
    // See #329.
    if (requestManager != null) {
        requestManager.onTrimMemory(level);
    }
}

然后RequestManager再調(diào)用Glide入口類的trimMemory來釋放更多內(nèi)存:

public void onTrimMemory(int level) {
    glide.trimMemory(level);
}

2.0.7 生命周期回調(diào)流程總結(jié)

在RequestManager構(gòu)造方法中益涧,還會(huì)將自身添加到LifeCycle中锈锤,這樣,整個(gè)流程就暢通了:

image

細(xì)心的可以發(fā)現(xiàn)闲询,雖然在構(gòu)造RequestManager時(shí)傳遞了參數(shù)RequestManagerTreeNode久免,但是在這個(gè)回調(diào)流程中,并沒有對(duì)所有后裔RMF的RequestManager進(jìn)行調(diào)用扭弧,Glide默認(rèn)確實(shí)是不會(huì)去調(diào)用阎姥,但這里并不意味著這些RequestManager不會(huì)被調(diào)用到,事實(shí)上鸽捻,當(dāng)前RMF生命周期被調(diào)用時(shí)呼巴,就意味后裔Fragment生命周期也會(huì)被調(diào)用,那么后裔Fragment這個(gè)流程仍然會(huì)走一遍御蒲,那么RequestManagerTreeNode到底有什么用呢?答案是沒用衣赶,完全沒用,如果只是簡(jiǎn)單使用Glide的話厚满。當(dāng)然府瞄,RequestManager暴露了相關(guān)接口給開發(fā)者使用:

public void resumeRequestsRecursive() {
    Util.assertMainThread();
    resumeRequests();
    for (RequestManager requestManager : treeNode.getDescendants()) {
        requestManager.resumeRequests();
    }
}

調(diào)用這個(gè)方法將會(huì)把所有后裔的請(qǐng)求同時(shí)一起處理。

本文轉(zhuǎn)自作者“他的大姨父”的Glide生命周期管理專題碘箍,如有侵權(quán)遵馆,請(qǐng)聯(lián)系作者效效進(jìn)行修改续崖,聯(lián)系方式在本簡(jiǎn)書的聲明中哦~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市团搞,隨后出現(xiàn)的幾起案子严望,更是在濱河造成了極大的恐慌,老刑警劉巖逻恐,帶你破解...
    沈念sama閱讀 222,807評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件像吻,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡复隆,警方通過查閱死者的電腦和手機(jī)拨匆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挽拂,“玉大人惭每,你說我怎么就攤上這事】髡唬” “怎么了台腥?”我有些...
    開封第一講書人閱讀 169,589評(píng)論 0 363
  • 文/不壞的土叔 我叫張陵,是天一觀的道長绒北。 經(jīng)常有香客問我黎侈,道長,這世上最難降的妖魔是什么闷游? 我笑而不...
    開封第一講書人閱讀 60,188評(píng)論 1 300
  • 正文 為了忘掉前任峻汉,我火速辦了婚禮,結(jié)果婚禮上脐往,老公的妹妹穿的比我還像新娘休吠。我一直安慰自己,他們只是感情好业簿,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評(píng)論 6 398
  • 文/花漫 我一把揭開白布瘤礁。 她就那樣靜靜地躺著,像睡著了一般辖源。 火紅的嫁衣襯著肌膚如雪蔚携。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,785評(píng)論 1 314
  • 那天克饶,我揣著相機(jī)與錄音酝蜒,去河邊找鬼。 笑死矾湃,一個(gè)胖子當(dāng)著我的面吹牛亡脑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 41,220評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼霉咨,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼蛙紫!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起途戒,我...
    開封第一講書人閱讀 40,167評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤坑傅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后喷斋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體唁毒,經(jīng)...
    沈念sama閱讀 46,698評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評(píng)論 3 343
  • 正文 我和宋清朗相戀三年星爪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了浆西。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,912評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡顽腾,死狀恐怖近零,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情抄肖,我是刑警寧澤久信,帶...
    沈念sama閱讀 36,572評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站憎瘸,受9級(jí)特大地震影響入篮,放射性物質(zhì)發(fā)生泄漏陈瘦。R本人自食惡果不足惜幌甘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望痊项。 院中可真熱鬧锅风,春花似錦、人聲如沸鞍泉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽咖驮。三九已至边器,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間托修,已是汗流浹背忘巧。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留睦刃,地道東北人砚嘴。 一個(gè)月前我還...
    沈念sama閱讀 49,359評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親际长。 傳聞我的和親對(duì)象是個(gè)殘疾皇子耸采,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 本文是Glide源碼解析系列的第一篇,通過這篇文檔工育,將可以了解到: 1.Glide如何綁定Activity虾宇、Fra...
    他的大姨父閱讀 8,654評(píng)論 6 42
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,332評(píng)論 25 707
  • 簡(jiǎn)介 kubernetes 是一個(gè)分布式的集群管理系統(tǒng),在每個(gè)節(jié)點(diǎn)(node)上都要運(yùn)行一個(gè) worker 對(duì)容器...
    shinwing閱讀 24,515評(píng)論 1 11
  • 聽說愛笑的人運(yùn)氣通常都不會(huì)太差如绸。 ————————————bela 累了文留。 - - - - - -Noansal
    三個(gè)遠(yuǎn)方閱讀 148評(píng)論 0 0
  • 小米和華為燥翅,堪稱手機(jī)圈的兩大巨擘,都是中國值得尊敬的企業(yè)蜕提。但是同樣是自主研發(fā)手機(jī)芯片森书,二者的待遇卻如此不同。 華為...
    45sfsf閱讀 364評(píng)論 0 0