深入理解與運用Android Jetpack ViewModel

在Android開發中,數據與界面的分離一直是一項重要的挑戰。為了解決這個問題,Google推出了Android Jetpack組件之一的ViewModel。ViewModel是一種用于管理UI相關數據的架構組件,它能夠幫助開發者實現優雅的數據驅動和生命周期管理。本文將深入淺出地介紹ViewModel的使用和原理,帶你一步步掌握這個強大的組件。

什么是ViewModel

ViewModel是Android Jetpack組件之一,它的主要目的是將UI控制器(如Activity和Fragment)與數據相關的業務邏輯分開,使得UI控制器能夠專注于展示數據和響應用戶交互,而數據的獲取和處理則交由ViewModel來管理。這種分離能夠使代碼更加清晰、易于測試和維護。

ViewModel的原理

ViewModel的原理其實并不復雜。在設備配置發生變化(如屏幕旋轉)導致Activity或Fragment重建時,ViewModel不會被銷毀,而是保留在內存中。這樣,UI控制器可以在重建后重新獲取之前的ViewModel實例,并繼續使用其中的數據,從而避免數據丟失和重復加載。

ViewModelStore和ViewModelStoreOwner

ViewModel的原理涉及兩個核心概念:ViewModelStore和ViewModelStoreOwner。

ViewModelStore是一個存儲ViewModel實例的容器,它的生命周期與UI控制器的生命周期關聯。在UI控制器(Activity或Fragment)被銷毀時,ViewModelStore會清理其中的ViewModel實例,避免內存泄漏。

ViewModelStoreOwner是擁有ViewModelStore的對象,通常是Activity或Fragment。ViewModelProvider通過ViewModelStoreOwner來獲取ViewModelStore,并通過ViewModelStore來管理ViewModel的生命周期。

ViewModelProvider

ViewModelProvider是用于創建和獲取ViewModel實例的工具類。它負責將ViewModel與ViewModelStoreOwner關聯,并確保ViewModel在合適的時機被銷毀。

在Activity中獲取ViewModel實例:

viewModel = new ViewModelProvider(this).get(MyViewModel.class);

在Fragment中獲取ViewModel實例:

viewModel = new ViewModelProvider(this).get(MyViewModel.class);

使用ViewModel

添加ViewModel依賴

首先,確保你的項目已經使用了AndroidX,并在build.gradle中添加ViewModel依賴:

dependencies {implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
}

創建ViewModel

創建ViewModel非常簡單,只需繼承ViewModel類并在其中定義數據和相關操作。

public class MyViewModel extends ViewModel {private MutableLiveData<String> data = new MutableLiveData<>();public LiveData<String> getData() {return data;}public void fetchData() {// 模擬異步數據獲取new Handler().postDelayed(() -> {data.setValue("Hello, ViewModel!");}, 2000);}
}

在UI控制器中使用ViewModel

在Activity或Fragment中獲取ViewModel的實例,并觀察數據變化:

viewModel = new ViewModelProvider(this).get(MyViewModel.class);
viewModel.getData().observe(this, data -> {// 更新UItextView.setText(data);
});viewModel.fetchData(); // 觸發數據獲取操作

ViewModel與跨組件通信

ViewModel不僅僅用于在單個UI控制器內部共享數據,它還可以用于在不同UI控制器之間共享數據,實現跨組件通信。例如,一個Fragment中的數據可以通過ViewModel傳遞給Activity。

在Activity中共享數據:

sharedViewModel = new ViewModelProvider(this).get(SharedViewModel.class);
sharedViewModel.getData().observe(this, data -> {// 更新UItextView.setText(data);
});

在Fragment中共享數據:

sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);

注意:在跨組件通信時,需要使用同一個ViewModelProvider獲取相同類型的ViewModel實例。在Activity中,使用this作為ViewModelProvider的參數,在Fragment中,使用requireActivity()作為參數。

ViewModel與SavedState

有時,我們可能希望在ViewModel中保存一些與UI控制器生命周期無關的數據,以便在重建時恢復狀態。ViewModel提供了SavedState功能,它可以讓我們在ViewModel中持久化保存數據。

示例代碼:

public class MyViewModel extends ViewModel {private SavedStateHandle savedStateHandle;public MyViewModel(SavedStateHandle savedStateHandle) {this.savedStateHandle = savedStateHandle;}public LiveData<String> getData() {return savedStateHandle.getLiveData("data");}public void setData(String data) {savedStateHandle.set("data", data);}
}

使用SavedStateViewModelFactory創建帶有SavedState功能的ViewModel:

public class MyActivity extends AppCompatActivity {private MyViewModel viewModel;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ViewModelProvider.Factory factory = new SavedStateViewModelFactory(getApplication(), this);viewModel = new ViewModelProvider(this, factory).get(MyViewModel.class);viewModel.getData().observe(this, data -> {// 更新UItextView.setText(data);});if (savedInstanceState == null) {// 第一次創建時,觸發數據獲取操作viewModel.fetchData();}}
}

ViewModel使用過程中的注意點

  • 不要在ViewModel中持有Context的引用,避免引發內存泄漏。
  • ViewModel應該只關注數據和業務邏輯,不應處理UI相關的操作。
  • 不要在ViewModel中保存大量數據,避免占用過多內存。
  • 當數據量較大或需要跨進程共享數據時,應該考慮使用其他解決方案,如Room數據庫或SharedPreferences。

結論

通過本文的介紹,你已經了解了Android Jetpack ViewModel的使用與原理。ViewModel的出現極大地簡化了Android開發中的數據管理和生命周期處理,使得應用更加健壯和高效。在實際開發中,合理使用ViewModel能夠幫助你構建優雅、易維護的Android應用。

Android 學習筆錄

Android 性能優化篇:https://qr18.cn/FVlo89
Android 車載篇:https://qr18.cn/F05ZCM
Android 逆向安全學習筆記:https://qr18.cn/CQ5TcL
Android Framework底層原理篇:https://qr18.cn/AQpN4J
Android 音視頻篇:https://qr18.cn/Ei3VPD
Jetpack全家桶篇(內含Compose):https://qr18.cn/A0gajp
Kotlin 篇:https://qr18.cn/CdjtAF
Gradle 篇:https://qr18.cn/DzrmMB
OkHttp 源碼解析筆記:https://qr18.cn/Cw0pBD
Flutter 篇:https://qr18.cn/DIvKma
Android 八大知識體:https://qr18.cn/CyxarU
Android 核心筆記:https://qr21.cn/CaZQLo
Android 往年面試題錦:https://qr18.cn/CKV8OZ
2023年最新Android 面試題集:https://qr18.cn/CgxrRy
Android 車載開發崗位面試習題:https://qr18.cn/FTlyCJ
音視頻面試題錦:https://qr18.cn/AcV6Ap

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

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

相關文章

C字符串練習題(6.3.1)

編寫一個程序&#xff0c;從鍵盤上讀入一個小于1000的正整數&#xff0c;然后創建并輸出一個字符串&#xff0c;說明該整數的值。例如&#xff0c;輸入941&#xff0c;程序產生的字符串是“Nine hundred and forty one”。 #include<stdlib.h> #include<string.h>…

前端HTML入門基礎

階段目標&#xff1a;掌握HTML、CSS常用布局技巧&#xff0c;能夠獨立制作網頁。 day01&#xff1a;HTML 基礎 目標&#xff1a;掌握標簽基本語法&#xff0c;能夠獨立布局文章頁。 01-今日課程介紹 今日目標&#xff1a;掌握標簽基本語法&#xff0c;能夠獨立布局文章頁。 核心…

SQL中CONVERT函數格式:CONVERT(data_type,expression[,style])

sqlserver convert()函數的使用方法_convert sqlserver_qq_37528515的博客-CSDN博客 SQL中CONVERT函數格式:CONVERT(data_type,expression[,style]) 說明&#xff1a; data_type:目標系統所提供的數據類型&#xff0c;如果轉換時沒有指定數據類型的長度&#xff0c;則 SQL Serv…

Maven基礎總結

前言 Maven 是一個項目管理工具&#xff0c;可以對 Java 項目進行構建、依賴管理。 基本要求掌握 配置Maven環境直接查。 得會在IDEA創建Maven的java項目吧、會創建Maven的web項目吧、會創建多模塊項目吧。 得會配置插件pligin、依賴dependency吧 一、Maven四大特性 1、…

CSS:服務器字體 與 響應式布局(用法 + 例子 + 效果)

文章目錄 服務器字體定義 服務器字體使用例子 響應式布局設備類型設備特性例子 服務器字體 解決字體不一致而產生的。 首先&#xff0c;在網上把字體下載好。 定義 服務器字體 font-face{font-family:字體名稱;src:url(字體資源路徑); }使用 在需要使用的選擇器里加上 font…

數學建模(一)前繼概念

課程推薦&#xff1a;數學建模老哥_嗶哩嗶哩_bilibili 目錄 一、什么是數學建模&#xff1f; 二、數學建模的一般步驟 三、數學建模賽題類型 1.預測型 2. 評價類 3.機理分析類 4. 優化類 一、什么是數學建模&#xff1f; 數學建模是利用數學方法解決實際問題的一種實踐。…

什么是多線程?進程和線程的區別是什么?如何使用Java實現多線程?

文章目錄 前言我們為什么要使用線程而不是進程來實現并發編程什么是線程進程和線程的區別如何使用Java實現多線程創建線程1.創建一個繼承 Thread 類的線程類2.實現 Runnable 接口匿名內部類方式實現 Runnable 接口lambda 表達式實現 Runnable 接口 Thread 類的常見構造方法Thre…

T113-S3-RTL8211網口phy芯片調試

目錄 前言 一、RTL8211介紹 二、硬件連接 三、設備樹配置 四、內核配置 五、phy芯片配置 六、調試問題 總結 前言 在嵌入式系統開發中&#xff0c;網絡連接是至關重要的一部分。T113-S3開發板搭載了RTL8211系列的網口PHY芯片&#xff0c;用于實現以太網連接。在開發過程…

C++ QT(二)

目錄 Qt 控件按鈕QPushButton控件簡介用法示例運行效果 QToolButton控件簡介用法示例運行效果 QRadioButton控件簡介用法示例運行效果 QCheckBox控件簡介用法示例運行效果 QCommandLinkButton控件簡介用法示例運行效果 QDialogButtonBox控件簡介用法示例運行效果 輸入窗口部件Q…

用 React+ts 實現無縫滾動的走馬燈

一、走馬燈的作用 走馬燈是一種常見的網頁交互組件&#xff0c;可以展示多張圖片或者內容&#xff0c;通過自動播放或者手動切換的方式&#xff0c;讓用戶能夠方便地瀏覽多張圖片或者內容。 本次實現的不是輪播圖而是像傳送帶一樣的無限滾動的形式。 二、需求梳理 走馬燈可設…

Go Gin 中使用 JWT

一、JWT JWT全稱JSON Web Token是一種跨域認證解決方案&#xff0c;屬于一個開放的標準&#xff0c;它規定了一種Token實現方式&#xff0c;目前多用于前后端分離項目和OAuth2.0業務場景下。 二、為什么要用在你的Gin中使用JWT 傳統的Cookie-Sesson模式占用服務器內存, 拓展性…

uniapp實現自定義導航內容高度居中(兼容APP端以及小程序端與膠囊對齊)

①效果圖如下 1.小程序端與膠囊對齊 2.APP端內容區域居中 注意&#xff1a;上面使用的是colorui里面的自定義導航樣式。 ②思路&#xff1a; 1.APP端和小程序端走不同的方法&#xff0c;因為小程序端要計算不同屏幕下右側膠囊的高度。 2.其次最重要的要清晰App端和小程序端…

【數學建模】清風數模更新5 灰色關聯分析

灰色關聯分析綜述 諸如經濟系統、生態系統、社會系統等抽象系統都包含許多因素&#xff0c;系統整體的發展受各個因素共同影響。 為了更好地推動系統發展&#xff0c;我們需要清楚哪些因素是主要的&#xff0c;哪些是次要的&#xff0c;哪些是積極的&#xff0c;哪些是消極的…

網絡基礎——網絡的由來與發展史

作者&#xff1a;Insist-- 個人主頁&#xff1a;insist--個人主頁 作者會持續更新網絡知識和python基礎知識&#xff0c;期待你的關注 目錄 一、網絡的由來 二、計算機網絡的發展史 1、第一階段 2、第二階段 3、第三階段 前言 每天都是使用網絡&#xff0c;那么你知道網絡…

FPGA----Vivado SDK創建并使用靜態鏈接庫(C/C++代碼移植)

1、在進行SoC開發時&#xff0c;PS端的C/C代碼可能涉及到核心算法需要移植操作&#xff0c;為此&#xff0c;本文講述了如何將C/C代碼打包為.a文件供程序調用 2、文章以我的程序為例&#xff0c;逐步講述代碼生成靜態鏈接庫并調用的方法。 下面是我程序的目錄結構&#xff0c…

spring boot實現實體類參數自定義校驗

安裝依賴項 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>1、新建實體類 Data public class UserEntity {private String name;private Integer age;…

RocketMQ 延遲消息

RocketMQ 延遲消息 RocketMQ 消費者啟動流程 什么是延遲消息 RocketMQ 延遲消息是指&#xff0c;生產者發送消息給消費者消息&#xff0c;消費者需要等待一段時間后才能消費到。 使用場景 用戶下單之后&#xff0c;15分鐘未支付&#xff0c;對支付賬單進行提醒或者關單處理…

PostgreSQL查詢慢sql原因和優化方案

PostgreSQL sql查詢慢優化方案有一下幾種解決方案&#xff1a; 1.關閉會話 查詢慢sql的執行會話&#xff0c;關閉進程。 查看數據庫后臺連接進程 SELECT count(*) FROM pg_stat_activity;SELECT * FROM pg_stat_activity; 查看數據庫后臺連接進程&#xff0c;但是此條SQL不…

python提取pdf圖片

import fitz import re import osdef save_pdf_img(path, save_path):path: pdf的路徑save_path : 圖片存儲的路徑# 使用正則表達式來查找圖片checkXO r"/Type(? */XObject)"checkIM r"/Subtype(? */Image)"# 打開pdfdoc fitz.open(path)# 圖片計數im…

用HARU-Net增強核分割:一種基于混合注意的殘差u塊網絡

文章目錄 Enhancing Nucleus Segmentation with HARU-Net: A Hybrid Attention Based Residual U-Blocks Network摘要本文方法損失函數后處理消融實驗 Enhancing Nucleus Segmentation with HARU-Net: A Hybrid Attention Based Residual U-Blocks Network 摘要 核圖像分割是…