ViewModel 原理

# ViewModel 原理

在現代Android應用開發中,ViewModel是架構組件庫的一個關鍵部分,它在提高應用的穩定性和性能方面發揮著重要作用。在這篇文章中,我們將深入探討ViewModel的工作原理和最佳實踐。

ViewModel簡介

ViewModel是Android Jetpack架構組件的一部分,它的主要目的是管理和存儲與UI相關的數據。ViewModel的設計初衷是使數據能夠在配置更改(如屏幕旋轉)后繼續存在。

工作原理

數據持久性

  • 當設備配置更改導致Activity重建時,ViewModel可以保留數據。它是通過系統保存的實例狀態來實現的,從而使數據在Activity重新創建時依然可用。

生命周期意識

  • ViewModel與Activity或Fragment的生命周期緊密相連。它在Activity或Fragment的整個生命周期內都是活躍的,并在它們被完全銷毀時清理。

使用ViewModel的優勢

  • 數據管理:ViewModel使得管理UI相關的數據更加簡單和高效。
  • 減少內存泄漏:由于ViewModel與視圖的生命周期是分離的,因此減少了因為持有Activity或Fragment引用而導致的內存泄漏的風險。
  • 更好的數據持久化:ViewModel可以在配置更改時保留重要數據,避免了不必要的數據庫或網絡請求。

實現ViewModel

創建ViewModel類

  • ViewModel的創建需要繼承ViewModel類。
  • 可以在ViewModel內部實現數據的加載和處理邏輯。

與Activity或Fragment關聯

  • ViewModel通過ViewModelProvider與Activity或Fragment綁定。
  • 這樣可以確保ViewModel的生命周期與Activity或Fragment的生命周期同步。

處理配置更改

  • 在配置更改(如屏幕旋轉)時,ViewModel幫助保存重要的UI數據。
  • 當Activity或Fragment重新創建時,可以從ViewModel中恢復數據。

最佳實踐

  • 避免在ViewModel中引用視圖:ViewModel不應持有對Activity、Fragment或View的引用。
  • 使用LiveData:LiveData可以用來觀察數據的變化,并在數據變化時更新UI。
  • 分離關注點:ViewModel應該專注于數據處理,而UI邏輯應該留在Activity或Fragment中。

ViewModel的創建方式

1. 使用ViewModelProvider

這是創建ViewModel的最常見方式。ViewModelProvider會與Activity或Fragment的生命周期關聯,確保在配置更改時ViewModel不會被重新創建。

import androidx.lifecycle.ViewModelProvider
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundleclass MainActivity : AppCompatActivity() {private lateinit var viewModel: MyViewModeloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)viewModel = ViewModelProvider(this).get(MyViewModel::class.java)}
}

在這個例子中,MyViewModel 是通過ViewModelProvider創建的,并與MainActivity的生命周期關聯。

2. 使用ViewModel的工廠方法

當需要向ViewModel傳遞參數時,可以使用ViewModel的工廠方法來創建ViewModel。

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundleclass MyViewModel(val myParam: String) : ViewModel() {// ViewModel的邏輯
}class MyViewModelFactory(private val myParam: String) : ViewModelProvider.Factory {override fun <T : ViewModel?> create(modelClass: Class<T>): T {if (modelClass.isAssignableFrom(MyViewModel::class.java)) {return MyViewModel(myParam) as T}throw IllegalArgumentException("Unknown ViewModel class")}
}class MainActivity : AppCompatActivity() {private lateinit var viewModel: MyViewModeloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val factory = MyViewModelFactory("Hello")viewModel = ViewModelProvider(this, factory).get(MyViewModel::class.java)}
}

在這個例子中,MyViewModel 需要一個字符串參數。因此,創建了一個MyViewModelFactory
來傳遞這個參數,并使用這個工廠來創建MyViewModel的實例。


ViewModel 相關面試題及回答

面試題1: ViewModel是什么,它是如何工作的?

  • 回答:
    ViewModel是一個架構組件,它的主要職責是管理界面控制器(如Activity和Fragment)的數據。它幫助保存數據,以便在配置更改(如屏幕旋轉)時數據不會丟失。ViewModel的實例與特定的Activity或Fragment的生命周期綁定,但比單個Activity或Fragment的實例生命周期更長,因此能夠在界面控制器重建時保持數據狀態。

面試題2: 為什么在ViewModel中持有Activity的引用是一個不好的實踐?

  • 回答:
    在ViewModel中持有Activity的引用會導致內存泄露,因為ViewModel的生命周期比它所關聯的Activity長。如果ViewModel持有Activity的引用,即使Activity需要被銷毀以釋放資源,由于ViewModel的存在,它無法被垃圾回收器回收,從而導致內存泄漏。

面試題3: LiveData是什么,它如何與ViewModel配合使用?

  • 回答:
    LiveData是一個可觀察的數據存儲器類,特別是用于保存可觀察數據,并且能在數據改變時通知視圖。它與ViewModel配合使用,因為LiveData遵循觀察者模式,這使得當數據改變時,UI可以立即更新。LiveData也是生命周期感知的,這意味著它只會在Activity或Fragment處于活躍狀態時更新UI,從而避免內存泄漏。

面試題4: 如何在ViewModel中處理耗時任務?

  • 回答:
    在ViewModel中處理耗時任務(如網絡請求)時,應該使用后臺線程來避免阻塞UI線程。可以利用協程或RxJava等異步處理框架來實現。這些任務應該與ViewModel的生命周期關聯,以確保在ViewModel被銷毀時,相關的異步任務也會相應地被取消或清理,以避免內存泄露。

面試題5: 解釋ViewModel的onCleared()方法。

  • 回答: onCleared()
    方法在ViewModel即將被銷毀時調用,這通常發生在與其關聯的Activity或Fragment被永久銷毀時(不是由于配置更改)。這個方法是清理資源的理想位置,比如取消所有進行中的異步任務、移除監聽器或者釋放對外部資源的引用。

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

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

相關文章

ubuntu安裝Avahi發現服務工具

一、簡介 解決設置固定ip后無法連接外網的問題&#xff0c;目前采用動態獲取ip&#xff0c;可以不用設置設備的固定IP&#xff0c;直接可以通過域名來訪問設備&#xff0c;類似樹莓派的連接調試 二、安裝 本文使用的是ubuntu23.10.1上安裝 1.安裝工具 sudo apt install av…

2.模擬問題——4.日期問題

日期問題難度并不大&#xff0c;但是代碼量非常大&#xff0c;需要較高的熟練度&#xff0c;因此需要著重練習&#xff0c;主要涉及數組和循環兩個方面的知識點&#xff0c;需要熟練的測試代碼。 兩個經典題型 閏年 閏年滿足以下兩個條件的任意一個 能夠被400整除不能夠被1…

MyBatis攔截器實現打印完整SQL語句

我們在執行語句的時候會使用Mybatis自帶的日志打印工具&#xff0c;但是打印的時候參數會用?代替&#xff0c;顯得看起來不是那么直觀&#xff0c;所以通過實現了InnerInterceptor接口&#xff0c;并重寫了beforeQuery和beforeUpdate方法。在這兩個方法中&#xff0c;它會獲取…

【Acwing】差分矩陣

圖1&#xff1a;a和b數組映射表 由于a是b的前綴和數組&#xff0c;因此改變b[ x1][ y1]之后&#xff0c;受到影響的a中元素如右半圖所示 圖2&#xff1a;求b數組的前綴和 #include<bits/stdc.h> using namespace std;int n,m,q; int a[1010][1010]; int b[1010][1010]…

work 3/1

1>機械臂 #include <head.h> #define SER_POTR 8899 #define SER_IP "192.168.125.223" int main(int argc, const char *argv[]) {//創建套接字int cfdsocket(AF_INET,SOCK_STREAM,0);if(cfd-1){perror("");return -1;}//鏈接struct sockaddr_i…

一文搞懂瀏覽器緩存機制

文章目錄 概述強制緩存協商緩存總結參考文章 概述 瀏覽器的緩存機制也就是我們說的HTTP緩存機制&#xff0c;其機制是根據HTTP報文的緩存標識進行的 瀏覽器第一次向服務器發送HTTP請求, 瀏覽器拿到請求結果后&#xff0c;會根據響應報文的緩存標識&#xff0c;決定是否進行緩存…

機器學習:數據處理基操

在處理完數據之后&#xff0c;選擇好模型&#xff0c;就可以用訓練集訓練模型&#xff0c;用測試集輸入模型 然后輸出需要預測的結果啦&#xff5e; 一、模塊導入 import numpy as np import pandas as pd #讀入數據 二、pandas數據 一、dataframe基礎 一、dataframe的創建…

github新手使用詳解及環境搭建案例

對于 GitHub 的新手使用以及環境搭建&#xff0c;以下是詳細的步驟和案例&#xff1a; 一、GitHub 新手使用詳解 注冊 GitHub 賬號&#xff1a;首先&#xff0c;你需要在 GitHub 官網上注冊一個賬號。填寫必要的個人信息&#xff0c;如用戶名、郵箱和密碼等。注冊完成后&…

【代碼】Android|判斷asserts下的文件存在與否,以及普通文件存在與否

作者版本&#xff1a;Android 11及以上 主要是發現網上沒有完整的、能跑的代碼&#xff0c;不知道怎么回事&#xff0c;GPT給我重寫的。我只能保證這個代碼尊嘟能跑&#xff0c;不像其他的缺胳膊少腿的。 asserts 貼一下結果&#xff1a; boolean isAssertFileExists(String …

Nginx配置php起WoWSimpleRegistration服務

WoWSimpleRegistration服務的git地址&#xff1a; GitHub - TrinityCore/WoWSimpleRegistration: Simple Registration page for TrinityCore/AzerothCore/AshamaneCore/CMangos 下載WoWSimpleRegistration 首先git下載&#xff1a; git clone https://github.com/TrinityC…

kafka消費者接收不到消息

背景&#xff1a; 對kafka消息進行監聽&#xff0c;生產者發了消息&#xff0c;但是消費端沒有接到消息&#xff0c;監聽代碼 消費端&#xff0c;kafka配置 spring.kafka.bootstrap-serverskafka.cestc.dmp:9591 spring.kafka.properties.sasl.jaas.configorg.apache.kafka.…

29.HarmonyOS App(JAVA)通知

普通通知: 通知渠道,彈出消息后&#xff0c;自動消失 長文本通知 //多行文本通知 //圖片通知 //社交通知 //媒體通知--經測試&#xff0c;圖片無法顯示&#xff0c;文字不顯示 場景介紹 HarmonyOS提供了通知功能&#xff0c;即在一個應用的UI界面之外顯示的消息&#xff0c;主…

C++之結構體以及通訊錄管理系統

1&#xff0c;結構體基本概念 結構體屬于自定義的數據概念&#xff0c;允許用戶存儲不同的數據類型 2&#xff0c;結構體的定義和使用 語法&#xff1a;struct 結構體名{ 結構體成員列表}&#xff1b; 通過結構體創建變量的方式有三種&#xff1a; 1&#xff0c;struct …

【簡說八股】面試官:你知道什么是AOP么?

回答 AOP(Aspect-Oriented Programming)&#xff0c;即面向切面編程&#xff0c;是一種編程范式&#xff0c;它的主要思想是將應用程序中的橫切關注點&#xff08;如日志記錄、性能統計、安全控制等&#xff09;從業務邏輯中剝離出來&#xff0c;然后通過特殊的方式將這些橫切…

設計模式學習筆記 - 設計原則 - 8.迪米特法則(LOD)

前言 迪米特法則&#xff0c;是一個非常實用的原則。利用這個原則&#xff0c;可以幫我們實現代碼的 “高內聚、松耦合”。 圍繞下面幾個問題&#xff0c;來學習迪米特原則。 什么是 “高內聚、松耦合”&#xff1f;如何利用迪米特法則來實現 高內聚、松耦合&#xff1f;哪些…

程序員求職

程序員的金三銀四求職寶典 隨著春天的腳步漸近&#xff0c;對于許多程序員來說&#xff0c;一年中最繁忙、最重要的面試季節也隨之而來。金三銀四&#xff0c;即三月和四月&#xff0c;被廣大程序員視為求職的黃金時期。在這兩個月里&#xff0c;各大公司紛紛開放招聘&#xf…

技術實踐|百度安全「大模型內容安全」高級攻擊風險評測

1、引子 2023年10月16日&#xff0c;OWASP發布了《OWASP Top 10 for LLM Applications》&#xff0c;這對于新興的大語言模型安全領域&#xff0c;可謂一份綱領性的重要報告。 OWASP是開放式Web應用程序安全項目&#xff08;Open Web Application Security Project&#xff0…

【Linux網絡命令系列】ping curl telnet三劍客

&#x1f49d;&#x1f49d;&#x1f49d;歡迎來到我的博客&#xff0c;很高興能夠在這里和您見面&#xff01;希望您在這里可以感受到一份輕松愉快的氛圍&#xff0c;不僅可以獲得有趣的內容和知識&#xff0c;也可以暢所欲言、分享您的想法和見解。 推薦:kwan 的首頁,持續學…

【C++】vector的使用和模擬實現(超級詳解!!!!)

文章目錄 前言1.vector的介紹及使用1.1 vector的介紹1.2 vector的使用1.2.1 vector的定義1.2.2 vector iterator 的使用1.2.3 vector 空間增長問題1.2.3 vector 增刪查改1.2.4 vector 迭代器失效問題。&#xff08;重點!!!!!!&#xff09;1.2.5 vector 在OJ中有關的練習題 2.ve…

C++入門和基礎

目錄 文章目錄 前言 一、C關鍵字 二、命名空間 2.1 命名空間的定義 2.2 命名空間的使用 2.3 標準命名空間 三、C輸入&輸出 四、缺省參數 4.1 缺省參數的概念 4.2 缺省參數的分類 五、函數重載 5.1 函數重載的簡介 5.2 函數重載的分類 六、引用 6.1 引用的…