日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網(wǎng)站首頁 編程語言 正文

Fragment通過FragmentManager實現(xiàn)通信功能詳細講解_Android

作者:AllenC6 ? 更新時間: 2023-03-03 編程語言

一、自己的理解

本質(zhì)就是Fragment經(jīng)由同一個FragmentManager以觀察者模式的方式通信。

首先多個Fragment通過同一個實例做到觀察者模式的通信。

其次Fragment都是由FragmentManager來管理的,F(xiàn)ragemnt的重建數(shù)據(jù)的保存等,各種機制都由FragmentManager控制,所以選擇FragmentManager來當這個同一個實例是最合適不過。

所以一個經(jīng)由同一個FragmentManager以觀察者模式的方式通信就出現(xiàn)了。

二、使用

1.接收數(shù)據(jù)

FragmentManager.setFragmentResultListener(
    requestKey,
    lifecycleOwner,
    FragmentResultListener { requestKey: String, result: Bundle ->
        在這里可以通過requestKey的判斷,來區(qū)別處理
    })
 

如果想在 Fragment 中接受數(shù)據(jù),可以在 FragmentManager 中注冊一個 FragmentResultListener,通過對requestKey 的判斷,區(qū)別處理 FragmentManager 發(fā)送的數(shù)據(jù)

setFragmentResultListener方法的參數(shù)中,攜帶著lifecycleOwner,它對生命周期進行了監(jiān)聽,只有在Started狀態(tài)之后才能接收信息,并且對Started狀態(tài)之前最后一次發(fā)送的數(shù)據(jù)有黏性,即Started之前發(fā)的最后一條消息,在Started狀態(tài)之后會收到,當lifecycleOwner生命周期到銷毀的時候會移除這個FragmentResultListener。

2.發(fā)送數(shù)據(jù)

FragmentManager.setFragmentResult(
    requestKey, 
    bundleOf(key to value) 
)
 

注意事項:

通信的Fragment要使用同一個FragmentManager來接收和發(fā)送信息。

舉例:

(1).如果在 FragmentA 中接收FragmentB 發(fā)送的數(shù)據(jù),F(xiàn)ragmentA 和 FragmentB 處于相同的層級,它們的共同點是被上一層級的FragmentManager所控制,parentFragmentManager就是他倆的同一個實例的FragmentManager,所以他們都通過parentFragmentManager來通信。

(2).如果在 FragmentA 中接受 FragmentB 發(fā)送的數(shù)據(jù),F(xiàn)ragmentA 是 FragmentB 的父容器,那對于FragemntA來說它和FragemntB的共同的FragmentManager是A的childFragmentManager,對于FragmentB來說它和A的共同的FragmentManager是B的parentFragmentManager,所以A接收B的消息用childFragmentManager,B發(fā)送A的消息用parentFragmentManager

三、源碼分析

1.發(fā)送數(shù)據(jù)

private final ConcurrentHashMap<String, Bundle> mResults = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, LifecycleAwareResultListener> mResultListeners =
        new ConcurrentHashMap<>();
@Override
public final void setFragmentResult(@NonNull String requestKey, @Nullable Bundle result) {
    if (result == null) {
        // mResults 是 ConcurrentHashMap 的實例,用來存儲數(shù)據(jù)傳輸?shù)?Bundle
        // 如果傳遞的參數(shù) result 為空,移除 requestKey 對應的 Bundle
        mResults.remove(requestKey);
        return;
    }
    // Check if there is a listener waiting for a result with this key
    // mResultListeners 是 ConcurrentHashMap 的實例,用來儲存注冊的 listener
    // 獲取 requestKey 對應的 listener
    LifecycleAwareResultListener resultListener = mResultListeners.get(requestKey);
    if (resultListener != null && resultListener.isAtLeast(Lifecycle.State.STARTED)) {
        // 如果 resultListener 不為空,并且生命周期處于 STARTED 狀態(tài)時,調(diào)用回調(diào)
        resultListener.onFragmentResult(requestKey, result);
    } else {
        // 否則保存當前傳輸?shù)臄?shù)據(jù)
        mResults.put(requestKey, result);
    }
}

我們看到這兩個集合:

private final Map<String, Bundle> mResults =
        Collections.synchronizedMap(new HashMap<String, Bundle>());
private final Map<String, LifecycleAwareResultListener> mResultListeners =
        Collections.synchronizedMap(new HashMap<String, LifecycleAwareResultListener>());

就明白,這就是觀察者模式保存觀察者的地方,再看發(fā)送數(shù)據(jù)的方法, 果然就是通過requestKey來找到對應的觀察者,然后調(diào)用onFragmentResult方法通知觀察者。

注意當resultListener生命周期狀態(tài)不到Started的時候,會先把數(shù)據(jù)保存mResults.put(requestKey, result);,在監(jiān)聽到生命周期狀態(tài)到Started時,會取一次數(shù)據(jù),然后這個mResults是一個map,所以只會保存最后一次put的數(shù)據(jù),所以在Started生命周期前發(fā)送的最后一次數(shù)據(jù),有黏性。

2.接收數(shù)據(jù)

private final ConcurrentHashMap<String, LifecycleAwareResultListener> mResultListeners =
        new ConcurrentHashMap<>();
@Override
public final void setFragmentResultListener(@NonNull final String requestKey,
                                            @NonNull final LifecycleOwner lifecycleOwner,
                                            @Nullable final FragmentResultListener listener) {
    // mResultListeners 是 ConcurrentHashMap 的實例,用來儲存注冊的 listener
    // 如果傳遞的參數(shù) listener 為空時,移除 requestKey 對應的 listener
    if (listener == null) {
        mResultListeners.remove(requestKey);
        return;
    }
    // Lifecycle是一個生命周期感知組件,一般用來響應Activity、Fragment等組件的生命周期變化
    final Lifecycle lifecycle = lifecycleOwner.getLifecycle();
    // 當生命周期處于 DESTROYED 時,直接返回
    // 避免當 Fragment 處于不可預知狀態(tài)的時,可能發(fā)生未知的問題
    if (lifecycle.getCurrentState() == Lifecycle.State.DESTROYED) {
        return;
    }
    // 開始監(jiān)聽生命周期
    LifecycleEventObserver observer = new LifecycleEventObserver() {
        @Override
        public void onStateChanged(@NonNull LifecycleOwner source,
                                   @NonNull Lifecycle.Event event) {
            // 當生命周期處于 ON_START 時開始處理數(shù)據(jù)
            if (event == Lifecycle.Event.ON_START) {
                // 開始檢查受到的數(shù)據(jù)
                Bundle storedResult = mResults.get(requestKey);
                if (storedResult != null) {
                    // 如果結(jié)果不為空,調(diào)用回調(diào)方法
                    listener.onFragmentResult(requestKey, storedResult);
                    // 清除數(shù)據(jù)
                    setFragmentResult(requestKey, null);
                }
            }
            // 當生命周期處于 ON_DESTROY 時,移除監(jiān)聽
            if (event == Lifecycle.Event.ON_DESTROY) {
                lifecycle.removeObserver(this);
                mResultListeners.remove(requestKey);
            }
        }
    };
    lifecycle.addObserver(observer);
    mResultListeners.put(requestKey, new FragmentManager.LifecycleAwareResultListener(lifecycle, listener));
}

Lifecycle是一個生命周期感知組件,一般用來響應Activity、Fragment等組件的生命周期變化

獲取 Lifecycle 去監(jiān)聽 Fragment 的生命周期的變化

當生命周期處于 ON_START 時開始處理數(shù)據(jù),避免當 Fragment 處于不可預知狀態(tài)的時,可能發(fā)生未知的問題

當生命周期處于 ON_DESTROY 時,移除監(jiān)聽

如果大家看過我的Lifecycle源碼分析的文章,就會很簡單的看出來這就是一個簡單的觀察者模式。

四、小結(jié)

這種方式只能傳遞簡單數(shù)據(jù)類型、Serializable 和 Parcelable 數(shù)據(jù),F(xiàn)ragment result APIs 允許程序從崩潰中恢復數(shù)據(jù),而且不會持有對方的引用,避免當 Fragment 處于不可預知狀態(tài)的時,可能發(fā)生未知的問題。

優(yōu)點:

在 Fragment 之間傳遞數(shù)據(jù),不會持有對方的引用

當生命周期處于 ON_START 時開始處理數(shù)據(jù),避免當 Fragment 處于不可預知狀態(tài)的時,可能發(fā)生未知的問題

當生命周期處于 ON_DESTROY 時,移除監(jiān)聽

原文鏈接:https://blog.csdn.net/m0_37707561/article/details/128503126

欄目分類
最近更新