Android學習總結之jetpack組件間的聯系

在傳統安卓開發中,UI 組件(Activity/Fragment)常面臨三個核心問題:

  1. 生命周期混亂:手動管理 UI 與數據的綁定 / 解綁,易導致內存泄漏(如 Activity 銷毀后回調仍在觸發)。
  2. 數據斷層:配置變更(如屏幕旋轉)導致 UI 重建時數據丟失,需重復加載。
  3. 代碼冗余:手動通過findViewById綁定 UI 元素,通過setOnClickListener處理交互,樣板代碼繁雜。

一、Lifecycle:生命周期管理的基石

核心作用:Lifecycle:劃定 “安全操作區間”

所有組件的行為都被 Lifecycle 的狀態機嚴格約束:

  • UI 組件(Activity/Fragment)實現LifecycleOwner,暴露自身生命周期(通過getLifecycle()獲取Lifecycle對象)。
  • ViewModel:在創建時通過ViewModelProvider與 UI 組件的 Lifecycle 綁定,僅在組件 “非銷毀周期”(即從onCreate到最終onDestroy,而非每次重建)內存活。例如,屏幕旋轉時 Activity 重建,ViewModel 會被緩存,直到用戶真正退出頁面。
  • LiveData:通過observe(LifecycleOwner, observer)綁定生命周期,僅在 UI 處于活躍狀態(STARTED/RESUMED)時通知數據變化。當 UI 進入 STOPPED 或 DESTROYED,自動斷開連接,避免回調到已銷毀的組件。
  • Data Binding:若在布局中聲明android:lifecycleOwner,生成的綁定類會監聽該 LifecycleOwner 的狀態,自動為 LiveData 注冊 / 注銷監聽器,確保綁定關系隨生命周期同步建立與銷毀。
與其他組件的關系
  1. ViewModel 的生命周期綁定
    ViewModel 的存在周期與組件(如 Activity)的?“非銷毀性” 生命周期?綁定(即從創建到組件永久銷毀,而非每次重建)。

    • ViewModel 通過實現?LifecycleOwner(或依賴?Lifecycle?對象),確保在組件銷毀(如因配置變更重建 Activity)時不會被立即回收,而是等待組件真正終止(如用戶退出應用)。
    • 底層依賴?LifecycleRegistry?監聽組件的?onDestroy?事件,觸發 ViewModel 的清理邏輯(如釋放資源)。
  2. LiveData 的生命周期感知
    LiveData 的數據訂閱必須關聯?LifecycleOwner(如 Activity/Fragment),確保僅在組件處于?活躍狀態(STARTED/RESUMED)時接收數據更新,避免在組件銷毀后回調導致的內存泄漏。

    • LiveData 內部通過?LifecycleBoundObserver?監聽?Lifecycle?狀態變化,當組件進入 STOPPED 或 DESTROYED 時,自動移除訂閱。
  3. Data Binding 的生命周期感知
    Data Binding 生成的綁定類若關聯?LifecycleOwner(如在布局中聲明?android:lifecycleOwner),可感知組件生命周期,確保綁定的數據觀察者(如 LiveData)在合適時機注冊 / 注銷,避免無效更新。

二、ViewModel:數據與邏輯的載體

核心作用:生命周期與 UI 解耦
  • 數據持久化:當 Activity 因配置變更重建時,ViewModel 不會被銷毀(存儲在ViewModelStore中),避免重復發起網絡請求或重新加載數據。例如,用戶旋轉屏幕后,ViewModel 中緩存的userData仍可用,直接通過 LiveData 通知新的 Activity 實例更新 UI。
  • 邏輯封裝:ViewModel 持有 LiveData 作為數據源,封裝業務邏輯(如處理網絡響應、數據轉換),但不持有 UI 引用(僅依賴 LifecycleOwner 的生命周期),避免內存泄漏。例如,ViewModel 中發起一個協程請求數據,協程會在 ViewModel 銷毀時自動取消(通過ViewModelCoroutineScope)。
  • 與 Lifecycle 的綁定:ViewModel 的創建由ViewModelProvider完成,該類會讀取 UI 組件的 Lifecycle,當 Lifecycle 進入ON_DESTROY(且組件非因配置變更銷毀,如用戶按返回鍵)時,觸發 ViewModel 的onCleared()方法,用于釋放資源(如關閉流、取消訂閱)。
與其他組件的關系
  1. 持有 LiveData 作為數據源
    ViewModel 通常將數據暴露為 LiveData 對象,供 UI 層(通過 Data Binding 或手動訂閱)觀察。

    • LiveData 的生命周期感知特性確保 ViewModel 中的數據僅在 UI 活躍時更新,ViewModel 自身無需關心 UI 組件的銷毀狀態。
    • 示例:
      class UserViewModel : ViewModel() {val userData = MutableLiveData<User>() // ViewModel 持有 LiveData
      }
      
  2. 與 Data Binding 的集成
    Data Binding 可直接在布局中引用 ViewModel 的屬性(包括 LiveData),通過?<variable name="viewModel" type="UserViewModel" />?聲明后,UI 元素可綁定為?android:text="@{viewModel.userData.name}"

    • 本質上,Data Binding 生成的綁定類會自動為 LiveData 注冊監聽器,當數據變化時觸發 UI 刷新。
  3. 依賴 Lifecycle 實現生命周期安全
    ViewModel 通過?ViewModelProvider?創建時,會關聯組件的?Lifecycle,確保自身在組件的非銷毀周期內存活。

    • 底層通過?ViewModelStore?與?Lifecycle?的?ON_DESTROY?事件聯動,在組件真正銷毀時釋放資源。

三、LiveData:數據變化的響應式橋梁

核心作用
  • 生命周期感知訂閱observe()方法必須傳入 LifecycleOwner,內部通過LifecycleBoundObserver監聽生命周期狀態。例如,當 Activity 進入后臺(STOPPED 狀態),LiveData 暫停發送更新;Activity 回到前臺(RESUMED),自動恢復發送。這避免了后臺頁面接收無效數據,節省電量和性能。
  • 數據變化的響應式分發:ViewModel 通過postValue()(子線程)或setValue()(主線程)更新數據,LiveData 會檢查所有訂閱的 LifecycleOwner 是否處于活躍狀態,僅通知活躍的 UI 組件。例如,多個 Fragment 訂閱同一個 LiveData,當數據變化時,只有可見的 Fragment 會收到通知。
與其他組件的關系
  1. ViewModel 與 UI 之間的 “粘合劑”

    • ViewModel 使用?MutableLiveData?存儲可變數據,通過?LiveData(不可變引用)暴露給 UI 層,實現數據的單向流動(ViewModel → UI)。
    • UI 層(Activity/Fragment)通過 Data Binding 或?observe()?方法訂閱 LiveData,當數據變化時自動更新 UI。
  2. 依賴 Lifecycle 實現安全訂閱
    LiveData.observe()?必須傳入?LifecycleOwner,內部通過?LifecycleRegistry?判斷組件狀態:

    • 當組件處于?DESTROYED?狀態(如 Activity 真正退出),自動移除訂閱,避免持有過期的 UI 引用。
    • 當組件因配置變更(如旋轉屏幕)重建時,新的 UI 組件會重新訂閱 LiveData,而 ViewModel 中的數據保持不變,實現無縫銜接。
  3. 與 Data Binding 的深度集成
    Data Binding 支持直接綁定 LiveData 對象,生成的綁定類會自動為 LiveData 添加?Observer,無需手動編寫?observe()?代碼。

    • 例如,布局中?android:text="@{viewModel.userData.name}"?會被解析為對?userData?的監聽,數據變化時觸發?TextView?的更新。

四、Data Binding:UI 與數據的自動化粘合劑

核心作用
  • 靜態綁定:直接映射 ViewModel 的普通屬性(如android:text="@{viewModel.username}"),當屬性變化時(需實現BaseObservable或使用 Kotlin 的ObservableField),自動調用notifyPropertyChanged()更新 UI。
  • 動態綁定 LiveData:無需手動調用observe(),Data Binding 生成的綁定類會自動為 LiveData 添加觀察者。例如,布局中android:text="@{viewModel.userData.name}"會被解析為對userData的監聽,當userData變化時,自動更新 TextView 的文本。
  • 雙向綁定:通過@={}語法(如android:text="@={viewModel.searchQuery}"),實現 UI 與 ViewModel 的雙向同步。本質上,Data Binding 為 EditText 設置onTextChangedListener,當用戶輸入時,自動將值賦給 ViewModel 的字段(需為MutableLiveData或可觀察屬性),形成 “UI→ViewModel→LiveData→UI” 的閉環。
與其他組件的關系
  1. 綁定 ViewModel 的屬性(包括 LiveData)

    • 在布局中聲明 ViewModel 類型的變量后,可直接引用其普通屬性或 LiveData 對象。
    • 對于 LiveData,Data Binding 會自動處理訂閱和取消訂閱,確保與組件生命周期同步。
  2. 依賴 Lifecycle 實現監聽清理
    當 Data Binding 的根布局聲明了?android:lifecycleOwner="@{viewModel}"(或關聯的 Activity/Fragment),綁定類會感知生命周期,在組件銷毀時自動解綁,避免內存泄漏。

  3. 雙向綁定與 ViewModel 的交互
    通過?@={}?語法支持雙向綁定(如 EditText 的輸入同步到 ViewModel 的字段),本質上是為 UI 元素設置監聽器,并將變化通知給 ViewModel,形成數據的雙向流動(UI ? ViewModel)。

    • 雙向綁定的字段通常為?LiveData?或普通可變屬性,結合 ViewModel 實現業務邏輯的解耦。

五、四者協作的核心流程

  1. 生命周期驅動初始化

    • Activity/Fragment 創建時,Lifecycle?狀態變為?CREATED,觸發 ViewModel 的創建(通過?ViewModelProvider),ViewModel 與組件的?Lifecycle?綁定。
    • Data Binding 初始化,生成綁定類并關聯 ViewModel,布局中的 LiveData 綁定自動注冊監聽(基于?LifecycleOwner)。
  2. 數據變化觸發 UI 更新

    • ViewModel 中的業務邏輯更新?MutableLiveData(如?userData.value = newUser)。
    • LiveData 檢測到數據變化,通過?LifecycleBoundObserver?檢查關聯的?LifecycleOwner?是否處于活躍狀態,若活躍則通知 Data Binding 生成的綁定類。
    • 綁定類更新對應的 UI 元素(如 TextView 的文本、ImageView 的圖片),無需手動調用?findViewById()?或設置回調。
  3. 生命周期結束時的資源釋放

    • 當 Activity/Fragment 進入?DESTROYED?狀態,Lifecycle?通知 ViewModel 清理資源(如取消未完成的協程),LiveData 自動移除所有訂閱,Data Binding 解綁所有 UI 引用,確保無內存泄漏。
擴展總結:
  1. 底層支撐:Lifecycle
    為所有組件提供統一的生命周期 “時鐘”,定義何時可以安全地進行數據操作(如 LiveData 發送更新)、何時需要釋放資源(如 ViewModel 清理內存)。沒有 Lifecycle,其他組件的生命周期安全將無法保障。

  2. 數據層:ViewModel + LiveData

    • ViewModel 作為 “數據管理者”,持有 LiveData 并封裝業務邏輯,確保數據在生命周期內穩定存在。
    • LiveData 作為 “數據傳輸者”,依托 Lifecycle 的狀態判斷,將數據精準推送給活躍的 UI,避免無效通信。
  3. UI 層:Data Binding
    作為連接數據與 UI 的 “橋梁”,通過編譯時生成的代碼,將 ViewModel 和 LiveData 的狀態直接映射到 UI 元素,消除手動操作的樣板代碼,同時借助 Lifecycle 自動管理綁定關系,避免內存泄漏。

六、登錄實戰解析

以 “用戶登錄” 場景為例,看四者如何協同工作:

  1. 初始化階段
    • Activity 創建,Lifecycle 狀態變為CREATED,通過ViewModelProvider獲取LoginViewModel(ViewModel 與 Activity 的 Lifecycle 綁定)。
    • Data Binding 初始化,解析布局文件,發現viewModel變量,生成ActivityLoginBinding類,綁定 ViewModel 到 UI 元素(如用戶名輸入框、登錄按鈕)。
    • 布局中android:text="@{viewModel.errorMsg}"觸發 Data Binding 為errorMsg(LiveData)自動注冊觀察者,該觀察者關聯 Activity 的 Lifecycle,僅在 Activity 活躍時接收錯誤信息。
  2. 用戶交互階段

    • 用戶點擊登錄按鈕,Data Binding 通過雙向綁定獲取輸入的賬號密碼,觸發 ViewModel 的login()方法。
    • ViewModel 中,login()發起網絡請求(如協程),成功后更新userData(MutableLiveData)的值:userData.value = loginResult
    • LiveData 檢測到數據變化,遍歷所有訂閱的 LifecycleOwner(當前 Activity 處于 RESUMED 狀態,為活躍狀態),通知 Data Binding 生成的綁定類更新 UI(如跳轉到主頁)。
  3. 配置變更階段(如屏幕旋轉)

    • Activity 銷毀并重建,Lifecycle 經歷DESTROYEDCREATED
    • ViewModel 因綁定 Activity 的 “非銷毀周期”,被ViewModelStore緩存,userData中的數據(如登錄狀態)保持不變。
    • 新 Activity 通過ViewModelProvider獲取到緩存的 ViewModel,Data Binding 重新綁定 UI,LiveData 自動向新 Activity 的 LifecycleOwner 注冊訂閱,UI 無需重新加載數據即可恢復狀態。
  4. 資源釋放階段

    • 用戶退出頁面,Activity 進入DESTROYED狀態,Lifecycle 通知 ViewModel 調用onCleared(),釋放協程等資源。
    • LiveData 檢測到所有訂閱的 LifecycleOwner 處于 DESTROYED,自動移除所有觀察者,避免持有 Activity 引用。
    • Data Binding 解綁所有 UI 元素與數據的連接,回收內存,確保無泄漏。

七、總結:四者的核心關系圖

UI 組件(Activity/Fragment)
│
├─ 實現 LifecycleOwner(提供 Lifecycle)
│
├─ 通過 ViewModelProvider 獲取 ViewModel(綁定 Lifecycle)
│  └─ ViewModel 持有 MutableLiveData(數據載體)
│
├─ Data Binding 綁定 ViewModel(布局中聲明 @{viewModel.data})
│  └─ 生成的綁定類自動訂閱 LiveData(基于 LifecycleOwner)
│
└─ LiveData.observe() 關聯 LifecycleOwner└─ 數據變化時,通過 Lifecycle 過濾無效狀態,通知 UI 更新

這四個組件通過?生命周期感知?和?數據驅動?形成閉環:

  • Lifecycle?確保所有組件的生命周期安全;
  • ViewModel?封裝數據與邏輯,隔離 UI 與業務;
  • LiveData?實現數據的響應式分發,避免無效更新;
  • Data Binding?簡化 UI 與數據的綁定,減少樣板代碼。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/903866.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/903866.shtml
英文地址,請注明出處:http://en.pswp.cn/news/903866.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++初階:類和對象(二)

大家好&#xff0c;我是小卡皮巴拉 文章目錄 目錄 一.運算符重載 1.1 基本概念 定義 參數規則 特性 選擇原則 重載要點 二.類的默認成員函數 2.1 構造函數 構造函數的特點 2.2 析構函數 析構函數的特點 2.3 拷貝構造函數 拷貝構造的特點 2.4 拷貝賦值運算符重…

【c++】【STL】priority_queue詳解

目錄 priority_queue的作用priority_queue的接口構造函數emptysizetoppushpopswap priority_queue的實現仿函數&#xff08;函數對象&#xff09;是什么&#xff1f;向上調整算法&#xff08;adjustup&#xff09;向下調整算法&#xff08;adjustdown&#xff09;迭代器構造pus…

測試——用例篇

目錄 1. 測試用例 1.1 概念 2. 設計測試用例的萬能公式 2.1 常規思考逆向思維發散性思維 2.2 萬能公式 3. 設計測試用例例的方法 3.1 基于需求的設計方法 ?編輯 3.2 具體的設計方法 3.2.1 等價類 3.2.2 邊界值 3.2.3 正交法 3.2.4 判定表法 3.2.5 場景法 3.2.6…

銷售總監求職簡歷模板

模板信息 簡歷范文名稱&#xff1a;銷售總監求職簡歷模板&#xff0c;所屬行業&#xff1a;其他 | 職位&#xff0c;模板編號&#xff1a;KREUNY 專業的個人簡歷模板&#xff0c;邏輯清晰&#xff0c;排版簡潔美觀&#xff0c;讓你的個人簡歷顯得更專業&#xff0c;找到好工作…

AE腳本 關鍵幀緩入緩出曲線調節工具 Flow v1.5.0 Win/Mac

Flow是一個非常好用的After Effects腳本,它可以讓你更加輕松自如地調整關鍵幀的速度曲線,無需觸碰老舊復雜的圖形編輯器。 AE腳本介紹 Flow為After Effects帶來了一個簡潔的界面,使自定義動畫曲線變得十分容易,無需深入研究速度和影響力這些讓人困惑的概念 - 只需繪制一個曲線…

ACGRIME:用于全局優化和特征選擇的自適應混沌高斯RIME優化器,附完整版免費代碼

自然現象中&#xff0c;軟冰的形成過程由 Set al. [42] 提出&#xff0c;軟冰是空氣中的過冷水滴在接觸固體物體并凍結時形成的。這種現象發生在特定的氣候條件下&#xff0c;當水蒸氣尚未凝結時&#xff0c;導致冰覆蓋的表面呈現出獨特的樹枝狀和葉子狀景觀。它在軟冰的生長和…

大模型開發學習筆記

文章目錄 大模型基礎大模型的使用大模型訓練的階段大模型的特點及分類大模型的工作流程分詞化(tokenization)與詞表映射 大模型的應用 進階agent的組成和概念planning規劃子任務分解ReAct框架 memory記憶Tools工具\工具集的使用langchain認知框架ReAct框架plan-and-Execute計劃…

4.27-5.4學習周報

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 摘要Abstract一、方法介紹2.Rainbow Memory(RM)2.1多樣性感知內存更新2.2通過數據增強增強樣本多樣性(DA) 二、使用步驟1.實驗概況2.RM核心代碼 總結 摘要 本博客概…

AI Rack架構高速互連的挑戰:損耗設計與信號完整性的設計框架

在AI驅動的時代&#xff0c;系統設計已經從單一PCB的視角&#xff0c;逐步轉向以整個rack為單位來考量。 對于信號完整性而言&#xff0c;焦點以不再局限于單一PCB上的損耗&#xff0c;而是擴展到芯片與芯片之間的端到端互連損耗&#xff08;end-to-end interconnect loss&…

杭電oj(1180、1181)題解

目錄 1180 題目 思路 問題概述 代碼思路分析 1. 數據結構與全局變量 2. BFS 函數 bfs 3. 主函數 main 總結 代碼 1181 題目 思路 1. 全局變量的定義 2. 深度優先搜索函數 dfs 3. 主函數 main 總結 代碼 1180 題目 思路 注&#xff1a;當走的方向和樓梯方向一…

軟件測試概念

這里寫目錄標題 需求開發模型軟件生命周期瀑布模型螺旋模型增量模型、迭代模型敏捷模型Scrum 測試模型V模型W模型&#xff08;雙V模型&#xff09; 需求 用戶需求&#xff1a;沒有經過合理的評估&#xff0c;通常就是一句話 軟件需求&#xff1a;是開發人員和測試人員執行工作…

數字基帶信號和頻帶信號的區別解析

數字基帶信號和數字頻帶信號是通信系統中兩種不同的信號形式&#xff0c;它們的核心區別在于是否經過調制以及適用的傳輸場景。以下是兩者的主要區別和分析&#xff1a; 1. 定義與核心區別 數字基帶信號&#xff08;Digital Baseband Signal&#xff09; 未經調制的原始數字信號…

Linux52 運行百度網盤 解決故障無法訪問repo nosandbox 未解決:疑似libstdc++版本低導致無法運行baidu網盤

昨日參考 哦 我是root Cannot find a valid baseurl for repo: centos-sclo-rh/x86_64 沒了 計劃去手動下一個 還是不行 放棄 猜測是 centos7 過期了 一些依賴組件也沒地方下載了 通過阿里云鏡像站下載 之前安裝的好像不是這個版本 還是計劃用yum去下載依賴&#xff0c;先處…

2000-2022年上市公司數字經濟專利申請數據

2000-2022年上市公司數字經濟專利申請數據 1、時間&#xff1a;2000-2022年 2、來源&#xff1a;國家知識產權局 3、指標&#xff1a;年份、股票代碼、股票簡稱、行業名稱、行業代碼、省份、城市、區縣、行政區劃代碼、城市代碼、區縣代碼、首次上市年份、上市狀態、數字經濟…

機器學習之五:基于解釋的學習

正如人們有各種各樣的學習方法一樣&#xff0c;機器學習也有多種學習方法。若按學習時所用的方法進行分類&#xff0c;則機器學習可分為機械式學習、指導式學習、示例學習、類比學習、解釋學習等。這是溫斯頓在1977年提出的一種分類方法。 有關機器學習的基本概念&#xff0c;…

Chromium 134 編譯指南 - Android 篇:安裝構建依賴項(七)

1. 引言 歡迎來到《Chromium 134 編譯指南》系列的第七篇文章&#xff01;在前面的章節中&#xff0c;我們已經成功獲取了Chromium源代碼&#xff0c;并將其配置為支持Android平臺。這些步驟為我們的編譯之旅奠定了堅實的基礎&#xff0c;但在開始實際編譯之前&#xff0c;我們…

java 進階 1.0

靜態方法 static 就是能直接用&#xff0c;不用再new一個對象了 一般java中Math等靜態類就是可以直接使用其方法 main函數里面不能包含太多的邏輯性語句&#xff0c;全部寫成模塊 寫好程序之后如何測試呢&#xff1f; 使用junit&#xff0c;不能在main函數里測試 測試本身就…

中小企業MES系統詳細設計

版本&#xff1a;V1.1 日期&#xff1a;2025年5月2日 一、設備協議兼容性設計 1.1 設備接入框架 #mermaid-svg-PkwqEMRIIlIBPP58 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-PkwqEMRIIlIBPP58 .error-icon{fill…

Spring Security會話管理

用戶認證通過后&#xff0c;為了避免用戶的每次操作都進行認證&#xff0c;可以將用戶的信息保存在會話中。會話就是系統為了保持當前用戶的登錄狀態所提供的機制&#xff0c;常見的有基于Session方式、基于Token方式等。Spring Security提供會話管理功能&#xff0c;只需要配置…

PostgreSQL數據庫操作基本命令

常用操作sql &#x1f510; 用戶管理 -- 創建用戶 CREATE USER username WITH PASSWORD password;-- 修改用戶密碼 ALTER USER username WITH PASSWORD newpassword;-- 刪除用戶 DROP USER username;&#x1f4e6; 數據庫操作 -- 創建數據庫 CREATE DATABASE dbname;-- 刪除…