智能座艙進階-應用框架層-Jetpack主要組件

Jetpack的分類
在這里插入圖片描述

1. DataBinding:以聲明方式將可觀察數據綁定到界面元素,通常和ViewModel配合使用。
2. Lifecycle:用于管理Activity和Fragment的生命周期,可幫助開發者生成更易于維護的輕量級代碼。
3. LiveData: 在底層數據庫更改時通知視圖。它是一個可觀察的數據持有者,與常規observable不同,LiveData是生命周期感知的。
4. Navigation:處理應用內導航。
5. Paging:可以幫助開發者一次加載和顯示小塊數據,按需加載部分數據可減少網絡帶寬和系統資源的使用。
6. Room:友好、流暢的訪問SQLite數據庫。它在SQLite的基礎上提供了一個抽象層,允許更強大的數據庫訪問。
7. ViewModel: 以生命周期的方式管理界面相關的數據,通常和DataBinding配合使用,為開發者實現MVVM架構提供了強有力的支持。
8. WorkManager: 管理Android的后臺的作業,即使應用程序退出或設備重新啟動也可以運行可延遲的異步任務。

Android 標準架構框架圖:
在這里插入圖片描述

Android官方架構部分的知識 https://developer.android.google.cn/topic/architecture/intro?hl=zh-cn

ViewBinding&DataBinding篇

ViewBinding介紹和使用

大家還是不要把ViewBinding和DataBinding這兩個不要混淆了.
ViewBindling 這是一個負責綁定View到代碼,減少 findViewId降低空引用資源ID錯誤。使用起來也較為簡單, 流程是:
第一、 在 app模塊下的build.gradle.kts下,打開使用ViewBinder的開關:

Android{
…
buildFeatures {ViewBinding = true}
}

第二就是需要在使用的Activity、fragment、view里面去初始化一下,inflate“

class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)val binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)}
}

第三步就可以直接引用使用了

binding.button.text="helloworld"

注意: viewBinding 目前能夠支持所有Xml的控件進行自動綁定, 包含Activity、Fragment以及其他View等。

ViewBinding原理

開啟后會自動生成【xml的文件名 自動大駝峰】+Binding.kt 文件。例如ActivityMainBinding.kt。可以看一下自動生成文件代碼,我只看inflate最后執行的部分:

public static ActivityMainBinding bind(@NonNull View rootView) { 
int id; 
id = R.id.tv1; 
TextView tv1 = ViewBindings.findChildViewById(rootView, id);if (tv1 == null) { 
break missingId; 
} 
id = R.id.tv2; 
TextView tv2 = ViewBindings.findChildViewById(rootView, id);
if (tv2 == null) { 
break missingId; 
} 
return new ActivityMainBinding((ConstraintLayout) rootView, tv1, tv2);} 
}

可以看到自動生成的代碼里,會把XML里控件的每個id都會塞進去,并且調findViewById進行綁定。

DataBinding的介紹和使用

Android 開發中體現 MVVM 架構思想的 Data Binding,其核心是 觀察者模式 的特定實現。首先,它有三個主要的實體:

  1. Data:與 View 相關的數據,它可以是 View 的可觀察者對象;
  2. View:展示給用戶的視圖,如果有交互功能且能更新數據,它可以是 Data 的可觀察者對象;
  3. ViewDataBinding:連接 Data 和 View 的中介,當 Data 或 View 作為可觀察者對象時,它充當可觀察者對象的代理。假如當我們寫了一個名為 demo.xml 的 Data Binding 的 layout 文件后,編譯工具會生成一個相應的類——DemoBinding,它的原型就是 ViewDataBinding。我們通常通過 DataBindingUtil.inflate(inflater, R.layout.demo, container, false) 來實例化的 DemoBinding 對象,即 ViewDataBinding。

主要是三個方面的功能:
? 將特定的 View 與特定的 Data 進行綁定,便于模塊化;
? View 自動感知和響應 Data 的變化,使得處理數據的業務層不必關心 View 的狀態,便于解耦;
? Data 也可以自動同步帶有交互功能的 View 對數據的修改,使得 UI 層的交互不必擔心數據是否能同步 View 狀態的問題,仍然便于解耦

使用類似ViewBinding:
第一是,在 app模塊下的build.gradle.kts下,打開使用ViewBinder的開關:

Android{
…
buildFeatures {DataBinding = true}
}

第二就可以直接在需要使用Xml文件里使用就行了,但是前提現有已經新簡的Data類:

class User(var firstName: String, var lastName: String) {}
<?xml version="1.0" encoding="utf-8"?> 
<layout xmlns:android="http://schemas.android.com/apk/res/android"><data> <variable name="user" type="com.example.User"/></data> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.firstName}"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.lastName}"/> </LinearLayout></layout>

基礎用法很簡單, 但是這只是單項View-Data綁定。
比較好的功能是 它還能幫助我們做到通過感知Data的局部變量來進行局部刷新,還有可以可以綁定View,進行雙向綁定。使用方法就是將Data轉化成observe 對象,并且添加@Bindable 的竹節,通過notifyPropertyChanged()方法來達成局部刷新,如下:

public class DemoData extends BaseObservable {private int element;
// 定義其它成員,省略
@Bindablepublic int getElement() {return this.element;}
public void setElement(int e) {this.element = e;notifyPropertyChanged(BR.element);}
// 省略其它成員操作
}

ViewModel篇

viewModel 的使用, viewModel繼承子類使用, 數據存儲在內存中,可以和acitivty 生命周期進行綁定,也獨立于Activity;onSaveInstanceState(Bundle) 存儲的數據,僅在當前應用進程哪有效, 當退出重新進入, Bundle重新恢復成初始狀態。或者在 OnStop中保存永久性數據

存儲作用域
實例化 ViewModel 時,您會向其傳遞實現 ViewModelStoreOwner 接口的對象。它可能是 Navigation 目的地、Navigation 圖表、activity、fragment 或實現接口的任何其他類型。然后,ViewModel 的作用域將限定為 ViewModelStoreOwner 的 Lifecycle。它會一直保留在內存中,直到其 ViewModelStoreOwner 永久消失。
有一系列類是 ViewModelStoreOwner 接口的直接或間接子類。直接子類為 ComponentActivity、Fragment 和 NavBackStackEntry。如需查看間接子類的完整列表,請參閱 ViewModelStoreOwner 參考文檔。
當 ViewModel 的作用域 fragment 或 activity 被銷毀時,異步工作會在作用域限定到該 fragment 或 activity 的 ViewModel 中繼續進行。這是持久性的關鍵。
如需了解詳情,請參閱下文有關 ViewModel 生命周期的部分

我這里不去贅述 如何使用它, 我曾在上一家公司中對的Alios系統平臺, 使用TS語言設計了一個跟viewModel類似的 組件庫DataManager .主要的設計原則是觀察者綁定和職責分離原則。 本質上來講ViewModel 就是一個獨立的數據儲存類, 設計者在里面做了跟Activity的destory來消亡的【非因為配置改變導致的destory】,其實也可以做到完全獨立,消亡由開發者自己決定, 這樣就會很有趣了,多個activty可以共一個ViewModel實例.只是里面做了一些對象傳遞的封裝,就可以和LiveData進行配合使用。

  • ViewModelStore:用于存儲ViewModel實例的類,內部持有一個HashMap保存實例,ViewModelProvider會將創建好的ViewModel實例保存到ViewModelStore中,之后再需要此類ViewModel的實例時就直接從中讀取。
  • ViewModelProvider.Factory:前文已經提到,這是用于創建ViewModel實例的工廠,ViewModelProvider當需要ViewModel的實例又在ViewModelStore中沒有找到對應實例時就會調用工廠的create方法創建。
  • CreationExtras:前文也已提到,它用于在創建ViewModel實例時從外界向構造過程傳遞參數,內部持有一個MutableMap,以key-value的形式存儲和查找參數

ViewModelStore中的HashMap 設計應該是至少兩層以上的,在當初我設計的空間中,這里用的兩層, 并且因為是量產項目的原因, 加了一個些狀態機key值進行了耦合。 Android官方是直接保存的ViewModel的對象,這樣就只有一層了。
每個Acitivty都會有一個ViewModelStoreOwner ,這樣在開發者做項目的時候,就不需要關系每個Activity的獲取ViewModel的時候,就是綁定的哪一個。

public class ComponentActivity extends androidx.core.app.ComponentActivity implements

// 實現了 ViewModelStoreOwner 接口
ViewModelStoreOwner,
…{
private ViewModelStore mViewModelStore;
// 重寫了 ViewModelStoreOwner 接口的唯一的方法 getViewModelStore()
@NonNull
@Override
public ViewModelStore getViewModelStore() {
if (getApplication() == null) {
throw new IllegalStateException("Your activity is not yet attached to the "
+ “Application instance. You can’t request ViewModel before onCreate call.”);
}
ensureViewModelStore();
return mViewModelStore;
}
ViewModelProvider 的構造方法時 ,獲取 ViewModelStore 對象時,實際調用了 MainActivity#getViewModelStore() ,而 getViewModelStore() 實現在 MainActivity 的父類 ComponentActivity 中。
在返回 mViewModelStore 對象之前調用了 ensureViewModelStore()
void ensureViewModelStore() {
if (mViewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
// Restore the ViewModelStore from NonConfigurationInstances
mViewModelStore = nc.viewModelStore;
}
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
}


- onRetainNonConfigurationInstance 方法和 getLastNonConfigurationInstance 是成對出現的,跟 onSaveInstanceState 機制類似,只不過它是僅用作處理配置更改的優化。
- 返回的是 onRetainNonConfigurationInstance 返回的對象Activity 在因配置更改而銷毀重建過程中會先調用 onRetainNonConfigurationInstance 保存 viewModelStore 實例。 在重建后可以通過 getLastNonConfigurationInstance 方法獲取之前的 viewModelStore 實例。
另外,我們可以看一下 mViewModelStore ,銷毀的時機,其實是在生命周期的判斷Lifecycle.Event.ON_DESTROY 被摧毀并且 判斷是否是配置改變引起的isChangingConfigurations()來進行區分:
getLifecycle().addObserver(new LifecycleEventObserver() {@Overridepublic void onStateChanged(@NonNull LifecycleOwner source,@NonNull Lifecycle.Event event) {if (event == Lifecycle.Event.ON_DESTROY) {// Clear out the available contextmContextAwareHelper.clearAvailableContext();// And clear the ViewModelStoreif (!isChangingConfigurations()) {getViewModelStore().clear();}}}});...}

ViewModel 出現之前,Activity 可以使用 onSaveInstanceState() 方法保存,然后從 onCreate() 中的 Bundle 恢復數據,但此方法僅適合可以序列化再反序列化的少量數據(IPC 對 Bundle 有 1M 的限制),而不適合數量可能較大的數據,如用戶信息列表或位圖。 ViewModel 的出現完美解決這個問題。

LiveData篇

通常情況下LiveData都是配合viewModel使用,在某個具體的ViewModel類中定義LiveData數據,然后在對應的Activity或Fragment中觀察LiveData數據的變化,LiveData的使用使得我們不再將數據保存在Activity或Fragment中,減輕了Activity或Fragment的工作量,使得Activity或Fragment只負責界面的管理和顯示,而不在保存數據也不會受到數據的影響。但是也可以使用oberveForever()不綁定生命周期, 那就需要自己手動管理它的消亡。
核心方法

通過 observe(owner,observer) 向 LiveData 注冊觀察者
? 通過 observe(owner,observer) 向 LiveData 注冊觀察者,并且把 observer 包裝成一個 LifecycleBoundObserver,它是一個具有生命周期邊界的觀察者,因為這個觀察者只有當宿主處于 STARTED 或者 RESUMED 狀態的它才會接收數據,其他時候它是不會接收數據的。
? 把包裝好的 Observer 注冊到 Lifecycle 當中,handlerLifecycleEvent(event) 利用 Lifecycle 能力,它能感知宿主生命周期能力的關鍵地方。注冊時和宿主每次生命周期變化都會回調 onStateChanged() 方法,剛進去的時候會觸發方法的同步。
? 會判斷這個事件宿主是否被銷毀了,從而主動地把 Observer 從 LiveData 中移除掉,流程結束。如果不是 DESTORY,說明宿主當前的狀態發生了變化,它會觸發 activeStateChanged(boolean newActive) 方法,它會判斷當前 Observer 是否處于活躍的狀態,如果宿主的狀態為 STARTED,RESUMED 則會分發最新數據到每個觀察者。
? 進而調用 dispatchingValue(ObserverWrapper) 分發數據,如果 ObserverWrapper 為空則分發數據給 liveData 中存儲的所有觀察者,如果不為空,則分發數據給該 Observer。
? considerNotify(ObserverWrapper) 中先判斷觀察者所在的宿主不活躍,則不分發;接著如果 observer 的 mLastVersion 大于或等于 LiveData 的 mVersion 則不分發,防止重復發送數據;最后通過 observer.mObserver.onChanged((T) mData) 分發數據,同步 mVersion 數據。
? 那么 LiveData 先發送數據,后注冊的 Observer 能接收到數據嗎? 答案是可以的。

普通消息的發送
? postValue() 發送一條數據,它可以在任意線程使用的,里面實際使用了 Handler.post 先把這個事件發送到主線程,然后在調用 setValue() 發送數據;
? setValue() 代表著 LiveData 發送數據,每發送一次 mVersion++,另外 LifecycleBoundObserver 中也有一個,它代表這個 Observer 接收了幾次數據,在分發數據的時候,這兩個 version 會進行比對,防止數據重復發送;
? setValue() 里面也會觸發 dispatchingValue(ObserverWrapper),ObserverWrapper 為 null,dispatchingValue() 它會遍歷 Observer 集合里面所有觀察者,然后逐一調用 considerNotify(ObserverWrapper) 去做消息的分發。

此外,LiveData和 Room配合使用 時候,
LiveData 就是為了簡化room 的Dao查詢對象到 viewModel的過程, 返回LiveData對象, 查詢數據的操作就不需要自己去創建后臺線程 。 LiveData能夠自動完成。至于為什么Room的查詢使用LiveData對象就不需要自己起子線程。 是因為 當liveData做返回對象的時候,room的 查詢方法,會多使用一個ComputableLiveData類, 這里面會判斷是否有子線程,如果沒有,自己會自動起一個子線程去查詢,普通類型就會直接走SupportSQLiteDatabase#query(SupportSQLiteQuery)方法,看下面代碼:

并且使用LiveData.observe.能夠添加觀察者, 綁定fragment周期和數據的更新,只要LiveData的數據發生變化, 就會實時刷新:
普通數據類型的查詢:

/*** Wrapper for {@link SupportSQLiteDatabase#query(SupportSQLiteQuery)}.** @param query The Query which includes the SQL and a bind callback for bind arguments.* @return Result of the query.*/public Cursor query(SupportSQLiteQuery query) {assertNotMainThread();return mOpenHelper.getWritableDatabase().query(query);}

使用LiveData作為返回值時用到了ComputableLiveData類,此類在構造的時候就將RoomDatabase中的mQueryExecutor傳入了。如果在構造的時候沒有傳入自定義的Executor,那么會自動生成一個。會走這個方法:

 if (mQueryExecutor == null) {mQueryExecutor = ArchTaskExecutor.getIOThreadExecutor();}

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

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

相關文章

個人秋招總結

秋招總結 個人基本情況拿到offer的公司希望比較大但是主動放棄的簡歷沒過的&#xff0c;有名氣的公司&#xff08;一般的公司太多了不寫&#xff09;秋招感觸 個人基本情況 前言 僅用于個人總結&#xff0c;主要是寫給自己看的&#xff0c;也給別人一點參考 學歷 中國農業大學計…

docker 使用 xz save 鏡像

適用場景 如果docker save -o xxx > xxx 鏡像體積過大,可以使用 xz 命令壓縮。 命令 例如 save busybox:1.31.1 鏡像,其中 -T 是使用多核心壓縮,可以加快壓縮。 docker save busybox:1.31.1 |xz -T 8 > /tmp/busybox:1.31.1安裝 xz Ubuntu/Debian sudo apt upda…

PowerMILL 客制化宏 - 變量

從PowerMILL2012起&#xff0c;命令起始支持變量。支持變量將使宏命令更加靈活和功能強大。可以對變量做一些運算而不依賴其它語言。 當前支持有變量類型為&#xff1a; INT&#xff1b; REAL&#xff1b; STRING&#xff1b; ENTITY&#xff1b; ARRAY LIST; OBJECT; 以下就…

arcgis for js實現地圖截圖、地圖打印

地圖截圖 效果 實現 復制運行即可 要實現復雜的截圖保存可以參考 官網案例 <!DOCTYPE html> <html lang"zn"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" />…

【BUG】記一次context canceled的報錯

文章目錄 案例分析gorm源碼解讀gin context 生命周期context什么時候cancel的什么時候context會被動cancel掉呢&#xff1f; 野生協程如何處理 案例分析 報錯信息 {"L":"ERROR","T":"2024-12-17T11:11:33.0050800","file"…

信號槽【QT】

文章目錄 對象樹字符集信號槽QT坐標系信號與槽connect自定義槽自定義信號disconnect 對象樹 #ifndef MYLABEL_H #define MYLABEL_H#include<QLabel> class MyLabel : public QLabel { public:// 構造函數使用帶 QWidget* 版本的.// 確保對象能夠加到對象樹上MyLabel(QWi…

寫SQL太麻煩?免費搭建 Text2SQL 應用,智能寫 SQL | OceanBase AI 實踐

自OceanBase 4.3.3版本推出以來&#xff0c;向量檢索的能力受到了很多客戶的關注&#xff0c;也紛紛表達希望OB能拓展更多 多模數據庫大模型 的AI應用實踐。 在上篇文章 &#x1f449; OceanBase LLM&#xff0c;免費構建你的專屬 AI 助手 &#xff0c;我們介紹了如何去搭建一…

400G/800G光模塊崛起:AI時代的網絡基礎設施革命

隨著AI技術的不斷成熟&#xff0c;各行各業都在大規模投入AI。醫療行業通過AI技術實現了更精準的診斷和治療&#xff1b;金融行業通過AI技術提高了風險管理能力&#xff1b;制造行業通過AI技術優化了生產流程&#xff1b;娛樂行業通過AI技術創造了更加豐富的用戶體驗。AI在醫療…

Dalsa線陣CCD相機使用開發手冊

要使用Dalsa工業相機進行二次開發&#xff0c;看用戶開發手冊順便做下筆記&#xff1a;&#xff08;歡迎加QQ討論&#xff1a;77248031&#xff0c; 或QQ群&#xff1a;585068192&#xff09; 由于“本公主”用的.NET開發&#xff0c;軟件支持只翻譯了手冊中.NET部分&#xff0…

C++特殊類設計(單例模式等)

目錄 引言 1.請設計一個類&#xff0c;不能被拷貝 2. 請設計一個類&#xff0c;只能在堆上創建對象 為什么設置實例的方法為靜態成員呢 3. 請設計一個類&#xff0c;只能在棧上創建對象 4. 請設計一個類&#xff0c;不能被繼承 5. 請設計一個類&#xff0c;只能創建一個對…

分布式系統架構:服務容錯

1.為什么需要容錯 分布式系統的本質是不可靠的&#xff0c;一個大的服務集群中&#xff0c;程序可能崩潰、節點可能宕機、網絡可能中斷&#xff0c;這些“意外情況”其實全部都在“意料之中”。故障的發生是必然的&#xff0c;所以需要設計一套健壯的容錯機制來應對這些問題。 …

【Latex手冊】自用

收錄Latex使用文檔/工具 個人使用時候的tips&#xff0c;僅供個人使用 核心網頁&#xff1a;LaTeX 工作室 【1】首頁 | LaTeX 知識庫 &#xff08;有詳細的入門教程&#xff09; 【2】LaTeX工作室 - LaTeX工作室&#xff08;一些模板&#xff09; 【3】LaTeX 工作室 &…

Pytorch應用實戰(1)- 基于YOLO的視頻人臉馬賽克處理

免費鏈接: Blogger(需翻Q), Github 文章目錄 本文介紹給圖片的人臉打碼給視頻的人臉打碼本文介紹 YoloV11(Github)提供了非常方便的API幫助用戶實現目標檢測(detect)、語義分割(segement)、肢體識別(Pose)等功能。 本文將基于YoloV11的目標檢測來實現一個視頻人臉馬…

[IT項目管理]九.項目質量管理

九&#xff0e;項目質量管理 9.1項目質量管理的重要性 對于很多IT項目的差勁&#xff0c;大多數人只可以忍受。項目質量管理是IT項目管理的重要組成部分&#xff0c;對于提高項目成功率、降低項目成本、提升客戶滿意度至關重要。盡管很多人對IT項目的質量問題感到無奈&#x…

【Threejs】從零開始(六)--GUI調試開發3D效果

請先完成前置步驟再進行下面操作&#xff1a;【Threejs】從零開始&#xff08;一&#xff09;--創建threejs應用-CSDN博客 一.GUI界面概述 GUI&#xff08;Graphical User Interface&#xff09;指的是圖形化用戶界面&#xff0c;廣泛用在各種程序的上位機&#xff0c;能夠通過…

ffmpeg-SDL顯示BMP

效果圖如下 本文主要將我們通過創建窗口、渲染上下文工具、紋理工具、矩形框工具&#xff1b;其需要主要的是&#xff1a;首先我們在顯示BMP時&#xff0c;需要先創建好窗口&#xff0c;再使用渲染工具對窗口進行格式刷&#xff0c;使用紋理工具和渲染工具配合進行BMP圖片顯示…

多音軌視頻使用FFmpeg刪除不要音軌方法

近期給孩子找宮崎駿動畫&#xff0c;但是有很多是多音軌視頻但是默認的都是日語&#xff0c;電視上看沒辦法所以只能下載后刪除音軌文件只保留中文。 方法分兩步&#xff0c;先安裝FFmpeg在轉文件即可。 第一步FFmpeg安裝 FFmpeg是一個開源項目&#xff0c;包含了處理視頻的…

基礎二分查找總結題-單峰序列2類做法

&#x1f330;單峰序列題目描述 晴問算法 題目描述&#xff1a; 單峰序列是指&#xff0c;在這個序列中存在一個位置&#xff0c;滿足這個位置的左側&#xff08;含該位置&#xff09;是嚴格遞增的、右側&#xff08;含該位置&#xff09;是嚴格遞減的&#xff0c;這個位置被…

【SH】Ubuntu Server 24搭建Web服務器訪問Python程序研發筆記

文章目錄 說個問題寫個方案一、安裝Ubuntu Server二、安裝Web服務器采用Nginx服務器 三、安裝Python及依賴創建項目虛擬環境 四、安裝Python Web框架采用Flask框架創建和運行Flask應用&#xff08;以后的重點&#xff09; 五、安裝WSGI服務器采用Gunicorn 六、配置Nginx七、驗證…

Vue3 重置ref或者reactive屬性值

需要重新定義一個對象綁定復制給原對象 。 實例代碼: const data () > ({groupId: ,groupCode: ,groupName: ,groupType: ,});const formData ref(data());//重置對象值 const reset()>{Object.assign(formData, data()…