網(wǎng)站首頁 編程語言 正文
一、自己的理解
本質(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
相關推薦
- 2022-09-28 基于OpenCV(python)的實現(xiàn)文本分割之垂直投影法_python
- 2022-12-15 詳解C#中HttpClient的用法及相關問題的解決方法_C#教程
- 2023-07-14 react 中redux的使用步驟
- 2023-02-02 Nginx顯示500錯誤的原因以及解決方法_nginx
- 2022-08-01 Android?WebView軟鍵盤遮擋輸入框方案詳解_Android
- 2022-11-05 Swift?Access?Control訪問控制與斷言詳細介紹_Swift
- 2022-05-25 在Windows平臺安裝Jenkins_win服務器
- 2022-07-09 Jquery操作DOM元素方法詳解_jquery
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支