網站首頁 編程語言 正文
一、自己的理解
本質就是Fragment經由同一個FragmentManager以觀察者模式的方式通信。
首先多個Fragment通過同一個實例做到觀察者模式的通信。
其次Fragment都是由FragmentManager來管理的,Fragemnt的重建數據的保存等,各種機制都由FragmentManager控制,所以選擇FragmentManager來當這個同一個實例是最合適不過。
所以一個經由同一個FragmentManager以觀察者模式的方式通信就出現了。
二、使用
1.接收數據
FragmentManager.setFragmentResultListener(
requestKey,
lifecycleOwner,
FragmentResultListener { requestKey: String, result: Bundle ->
在這里可以通過requestKey的判斷,來區別處理
})
如果想在 Fragment 中接受數據,可以在 FragmentManager 中注冊一個 FragmentResultListener,通過對requestKey 的判斷,區別處理 FragmentManager 發送的數據
setFragmentResultListener方法的參數中,攜帶著lifecycleOwner,它對生命周期進行了監聽,只有在Started狀態之后才能接收信息,并且對Started狀態之前最后一次發送的數據有黏性,即Started之前發的最后一條消息,在Started狀態之后會收到,當lifecycleOwner生命周期到銷毀的時候會移除這個FragmentResultListener。
2.發送數據
FragmentManager.setFragmentResult(
requestKey,
bundleOf(key to value)
)
注意事項:
通信的Fragment要使用同一個FragmentManager來接收和發送信息。
舉例:
(1).如果在 FragmentA 中接收FragmentB 發送的數據,FragmentA 和 FragmentB 處于相同的層級,它們的共同點是被上一層級的FragmentManager所控制,parentFragmentManager就是他倆的同一個實例的FragmentManager,所以他們都通過parentFragmentManager來通信。
(2).如果在 FragmentA 中接受 FragmentB 發送的數據,FragmentA 是 FragmentB 的父容器,那對于FragemntA來說它和FragemntB的共同的FragmentManager是A的childFragmentManager,對于FragmentB來說它和A的共同的FragmentManager是B的parentFragmentManager,所以A接收B的消息用childFragmentManager,B發送A的消息用parentFragmentManager
三、源碼分析
1.發送數據
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 的實例,用來存儲數據傳輸的 Bundle
// 如果傳遞的參數 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 狀態時,調用回調
resultListener.onFragmentResult(requestKey, result);
} else {
// 否則保存當前傳輸的數據
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>());
就明白,這就是觀察者模式保存觀察者的地方,再看發送數據的方法, 果然就是通過requestKey來找到對應的觀察者,然后調用onFragmentResult方法通知觀察者。
注意當resultListener生命周期狀態不到Started的時候,會先把數據保存mResults.put(requestKey, result);,在監聽到生命周期狀態到Started時,會取一次數據,然后這個mResults是一個map,所以只會保存最后一次put的數據,所以在Started生命周期前發送的最后一次數據,有黏性。
2.接收數據
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
// 如果傳遞的參數 listener 為空時,移除 requestKey 對應的 listener
if (listener == null) {
mResultListeners.remove(requestKey);
return;
}
// Lifecycle是一個生命周期感知組件,一般用來響應Activity、Fragment等組件的生命周期變化
final Lifecycle lifecycle = lifecycleOwner.getLifecycle();
// 當生命周期處于 DESTROYED 時,直接返回
// 避免當 Fragment 處于不可預知狀態的時,可能發生未知的問題
if (lifecycle.getCurrentState() == Lifecycle.State.DESTROYED) {
return;
}
// 開始監聽生命周期
LifecycleEventObserver observer = new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
// 當生命周期處于 ON_START 時開始處理數據
if (event == Lifecycle.Event.ON_START) {
// 開始檢查受到的數據
Bundle storedResult = mResults.get(requestKey);
if (storedResult != null) {
// 如果結果不為空,調用回調方法
listener.onFragmentResult(requestKey, storedResult);
// 清除數據
setFragmentResult(requestKey, null);
}
}
// 當生命周期處于 ON_DESTROY 時,移除監聽
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 去監聽 Fragment 的生命周期的變化
當生命周期處于 ON_START 時開始處理數據,避免當 Fragment 處于不可預知狀態的時,可能發生未知的問題
當生命周期處于 ON_DESTROY 時,移除監聽
如果大家看過我的Lifecycle源碼分析的文章,就會很簡單的看出來這就是一個簡單的觀察者模式。
四、小結
這種方式只能傳遞簡單數據類型、Serializable 和 Parcelable 數據,Fragment result APIs 允許程序從崩潰中恢復數據,而且不會持有對方的引用,避免當 Fragment 處于不可預知狀態的時,可能發生未知的問題。
優點:
在 Fragment 之間傳遞數據,不會持有對方的引用
當生命周期處于 ON_START 時開始處理數據,避免當 Fragment 處于不可預知狀態的時,可能發生未知的問題
當生命周期處于 ON_DESTROY 時,移除監聽
原文鏈接:https://blog.csdn.net/m0_37707561/article/details/128503126
相關推薦
- 2022-04-20 Android實現環信修改頭像和昵稱_Android
- 2022-10-01 Redis+Caffeine實現分布式二級緩存組件實戰教程_Redis
- 2023-03-26 react組件實例屬性props實例詳解_React
- 2023-04-08 C#獲取時間戳的方法及時間戳轉換問題_C#教程
- 2022-04-22 C#基于WinForm實現串口通訊_C#教程
- 2022-10-03 Docker啟動失敗報錯Failed?to?start?Docker?Application?Con
- 2022-04-27 C++的指針,引用和STL詳解_C 語言
- 2021-12-09 C語言實現將double/float?轉為字符串(帶自定義精度)_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支