作者:heiyulong
原文:https://mp.weixin.qq.com/s/V2haCRugRYCGDZrA9iw7bQ
前言
本次主要講解的內(nèi)容:
1、Jetpack介紹
2、Jetpack架構(gòu)組件庫的相關(guān)用法
一、Jetpack 介紹
1、什么是Jetpack
google 官方解釋:
Jetpack 是一個由多個庫組成的套件,可幫助開發(fā)者遵循最佳做法,減少樣板代碼并編寫可在各種 Android 版本和設(shè)備中一致運(yùn)行的代碼,讓開發(fā)者精力集中編寫重要的代碼。
Jetpack 是 Google 為解決 Android 開發(fā)碎片化,打造成熟健康生態(tài)圈提出的戰(zhàn)略規(guī)劃,是 Google 對 Android 未來提出的發(fā)展方向,同時它也是眾多優(yōu)秀 Android 組件的集合。
2、為何使用 Android Jetpack
Google 官方解釋:
- 遵循最佳做法:Android Jetpack 組件采用最新的設(shè)計方法構(gòu)建,具有向后兼容性,可以減少崩潰和內(nèi)存泄露。
- 消除樣板代碼:Android Jetpack 可以管理各種繁瑣的 Activity(如后臺任務(wù)、導(dǎo)航和生命周期管理),以便您可以專注于打造出色的應(yīng)用。
- 減少不一致:這些庫可在各種 Android 版本和設(shè)備中以一致的方式運(yùn)作,助您降低復(fù)雜性。
Jetpack 的優(yōu)勢:
- Jetpack 擁有基于生命周期感知的能力,可以減少 NPE(空指針異常) 崩潰、內(nèi)存泄漏,為開發(fā)出健壯且流暢的程序提供強(qiáng)力保障;
- Jetpack 可以消除大量重復(fù)樣板式的代碼,可以加速 Android 的開發(fā)進(jìn)程,組件可搭配工作,也可單獨使用,同時配合 Kotlin 語言特性能夠顯著提高工作效率;
- 統(tǒng)一開發(fā)模式,拋棄傳統(tǒng)的 MVC, MVP;
3、JetPack 的構(gòu)成
如上圖:Jetpack 主要包括 4 個部分,分別是【Architecture:架構(gòu)】、【UI:界面】、【behavior:行為】和【foundation:基礎(chǔ)】。
Architecture,架構(gòu)組件
目的:幫助開發(fā)者設(shè)計穩(wěn)健、可測試且易維護(hù)的應(yīng)用;
- Lifecycle:具備宿主生命周期感知能力的組件 特性:持有組件(如 Activity 或 Fragment)生命周期狀態(tài)的信息,并且允許其他對象觀察此狀態(tài);
- LiveData:新一代具備生命周期感知能力的數(shù)據(jù)訂閱、分發(fā)組件 特性:支持共享資源、支持黏性事件的分發(fā)、不再需要手動處理生命周期、確保界面符合數(shù)據(jù)狀態(tài);
- ViewModel:具備生命周期感知能力的數(shù)據(jù)存儲組件 特性:頁面因配置變更導(dǎo)致的重啟,此時數(shù)據(jù)不丟失;可以實現(xiàn)跨頁面(跨 Activity)的數(shù)據(jù)共享;
- SavedState 架構(gòu)組件原理解析 特性:因內(nèi)存不足,電量不足導(dǎo)致頁面被回收時可以搭配 ViewModel 實現(xiàn)數(shù)據(jù)存儲與恢復(fù);
- Room:輕量級 orm 數(shù)據(jù)庫,本質(zhì)上是一個 SQLite 抽象層 特性:使用簡單(類似于 Retrofit 庫),通過注解的方式實現(xiàn)相關(guān)功能,編譯時自動生成相關(guān)實現(xiàn)類
- DataBinding:只是一種工具,解決的是 View 和數(shù)據(jù)之間的雙向綁定 特性:支持?jǐn)?shù)據(jù)與視圖雙向綁定、數(shù)據(jù)綁定空安全、減少模板代碼、釋放 Activity/Fragment 壓力;
- Paging: 列表分頁組件,可以輕松完成分頁預(yù)加載以達(dá)到無限滑動的效果 特性:巧妙融合 LiveData、提供多種數(shù)據(jù)源加載方式;不足之處:不支持列表數(shù)據(jù)增刪改,列表添加 HeaderView,F(xiàn)ooterView 定位不準(zhǔn)確;
- Navigation 組件原理分析:端內(nèi)統(tǒng)一路由組件 特性:能夠為 Activity,F(xiàn)ragment,Dialog,F(xiàn)loatWindow 提供統(tǒng)一的路由導(dǎo)航服務(wù),可以傳遞參數(shù),指定導(dǎo)航動畫,還支持深度鏈接等主要能力;不足:十分依賴 xml 配置文件不利于組件化,模塊化
- WorkManager:新一代后臺任務(wù)管理組件,service 能做的事情它都能做 特性:支持周期性任務(wù)調(diào)度、鏈?zhǔn)饺蝿?wù)調(diào)度、豐富的任務(wù)約束條件、程序即便退出,依舊能保證任務(wù)的執(zhí)行;
Foundationy,基礎(chǔ)組件
目的:提供橫向功能,例如向后兼容性、測試、安全、Kotlin 語言支持,并包括多個平臺開發(fā)的組件;
- Android KTX:優(yōu)化了供 Kotlin 使用的 Jetpack 和 Android 平臺 API,幫助開發(fā)者以更簡潔、更愉悅、更慣用的方式使用 Kotlin 進(jìn)行 Android 開發(fā);
- AppCompat:幫助較低版本的 Android 系統(tǒng)進(jìn)行兼容;
- Auto:開發(fā) Android Auto 應(yīng)用的組件,提供了適用于所有車輛的標(biāo)準(zhǔn)化界面和用戶交互;
- 檢測:從 AndroidStudio 中快速檢測基于 Kotlin 或 JAVA 的代碼;
- 多 Dex 處理:為具有多個 Dex 文件應(yīng)用提供支持;
- 安全:安全的讀寫加密文件和共享偏好設(shè)置;
- 測試:用于單元和運(yùn)行時界面測試的 Android 測試框架;
- TV:構(gòu)建可讓用戶在大屏幕上體驗沉浸式內(nèi)容的應(yīng)用;
- Wear OS:開發(fā) Wear 應(yīng)用的組件;
Behavior,行為組件
目的:幫助開發(fā)者的應(yīng)用與標(biāo)準(zhǔn) Android 服務(wù)(如通知、權(quán)限、分享)相集成;
- CameraX:幫助開發(fā)簡化相機(jī)應(yīng)用的開發(fā)工作,提供一致且易于使用的界面,適用于大多數(shù) Android 設(shè)備,并可向后兼容至 Android 5.0(API 21);
- DownloadManager:處理長時間運(yùn)行的 HTTP 下載的系統(tǒng)服務(wù);
- 媒體和播放:用于媒體播放和路由(包括 Google Cast)的向后兼容 API;
- 通知:提供向后兼容的通知 API,支持 Wear 和 Auto;
- 權(quán)限:用于檢查和請求應(yīng)用權(quán)限的兼容性 API;
- 設(shè)置:創(chuàng)建交互式設(shè)置,建議使用 AndroidX Preference Library 庫將用戶可配置設(shè)置集成到應(yīng)用中;
- 分享操作:可以更輕松地實現(xiàn)友好的用戶分享操作;
- 切片:切片是一種 UI 模板,創(chuàng)建可在應(yīng)用外部顯示應(yīng)用數(shù)據(jù)的靈活界面元素;
UI,界面組件
- Animation and Transition:該框架包含用于常見效果的內(nèi)置動畫,并允許開發(fā)者創(chuàng)建自定義動畫和生命周期回調(diào);
- Emoji Compatibility:即便用戶沒有更新 Android 系統(tǒng)也可以獲取最新的表情符號;
- Fragment:組件化界面的基本單位;
- 布局:用 XML 中聲明 UI 元素或者在代碼中實例化 UI 元素;
- 調(diào)色板:從調(diào)色板中提取出有用的信息;
注意:
上面的圖之前在官網(wǎng)是存在的,現(xiàn)在官網(wǎng)已經(jīng)找不到此圖,只有jetpack架構(gòu)組件的文檔入口;
猜想google官方也是旨在強(qiáng)化Architecture架構(gòu)組件,因為UI、Behavior、Foundation 這三部分大多是對已有內(nèi)容的收集整理。
所以接下來的關(guān)注點主要是在Architecture 架構(gòu)部分
4、Jetpack 與 AndroidX
參考官網(wǎng)Jetpack使用
1、Jetpack 庫可以單獨使用,也可以組合使用,以滿足應(yīng)用的不同需求。
2、Jetpack 庫在 androidx 命名空間中發(fā)布。
androidx介紹:
androidx 命名空間中的工件包含 Android Jetpack 庫。與支持庫一樣,androidx 命名空間中的庫與 Android 平臺分開提供,并向后兼容各個 Android 版本。
AndroidX 對原始 Android 支持庫進(jìn)行了重大改進(jìn),后者現(xiàn)在已不再維護(hù)。androidx 軟件包完全取代了支持庫,不僅提供同等的功能,而且提供了新的庫。
AndroidX 還包括以下功能:
AndroidX 中的所有軟件包都使用一致的命名空間,以字符串 androidx 開頭。支持庫軟件包已映射到對應(yīng)的 androidx.* 軟件包。有關(guān)所有舊類到新類以及舊構(gòu)建工件到新構(gòu)建工件的完整映射,請參閱軟件包重構(gòu)頁面。
與支持庫不同,androidx 軟件包會單獨維護(hù)和更新。從版本 1.0.0 開始,androidx 軟件包使用嚴(yán)格的語義版本控制。您可以單獨更新項目中的各個 AndroidX 庫。
版本 28.0.0 是支持庫的最后一個版本。我們將不再發(fā)布 android.support 庫版本。所有新功能都將在 androidx 命名空間中開發(fā)。
所以,目前我們的項目【樸新網(wǎng)校】、【樸新助教】、【數(shù)學(xué)寶典】都已經(jīng)遷移使用了androidx庫。
androidx遷移參照官網(wǎng)
注意:Jetpack 是各種組件庫的統(tǒng)稱,AndroidX 是這些組件的統(tǒng)一包名。
二、Jetpack架構(gòu)組件庫
1、應(yīng)用架構(gòu)指南
官網(wǎng)推薦應(yīng)用架構(gòu):
在項目中運(yùn)用到的框架的搭建基本基于改圖,運(yùn)用到的jetpack組件庫有ViewModel、LiveData、DataBinding;接下來逐一介紹他們的特性和用法。
2、ViewModel & LiveData
ViewModel 類旨在以注重生命周期的方式存儲和管理界面相關(guān)的數(shù)據(jù)。ViewModel 類讓數(shù)據(jù)可在發(fā)生屏幕旋轉(zhuǎn)等配置更改后繼續(xù)留存。

專欄
Go語言Web開發(fā)從入門到項目實戰(zhàn)
作者:猿芯
18幣
19人已購
查看
LiveData 是一種可觀察的數(shù)據(jù)存儲器類。與常規(guī)的可觀察類不同,LiveData 具有生命周期感知能力,意指它遵循其他應(yīng)用組件(如 Activity、Fragment 或 Service)的生命周期。這種感知能力可確保 LiveData 僅更新處于活躍生命周期狀態(tài)的應(yīng)用組件觀察者。
LiveData , ViewModel 組件都是基于Lifecycle來實現(xiàn)的,LiveData&ViewModel也是結(jié)合使用的,接下來具體看下如何使用
聲明依賴項
dependencies {
def lifecycle_version = "2.2.0"
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
}
實現(xiàn) ViewModel
架構(gòu)組件為界面控制器提供了 ViewModel 輔助程序類,該類負(fù)責(zé)為界面準(zhǔn)備數(shù)據(jù)。在配置更改期間會自動保留 ViewModel 對象,以便它們存儲的數(shù)據(jù)立即可供下一個 Activity 或 Fragment 實例使用。例如,如果您需要在應(yīng)用中顯示用戶列表,請確保將獲取和保留該用戶列表的責(zé)任分配給 ViewModel,而不是 Activity 或 Fragment,如以下示例代碼所示:
public class MyViewModel extends ViewModel {
private MutableLiveData<List<User>> users;
public LiveData<List<User>> getUsers() {
if (users == null) {
users = new MutableLiveData<List<User>>();
loadUsers();
}
return users;
}
private void loadUsers() {
// Do an asynchronous operation to fetch users.
}
}
然后,您可以從 Activity 訪問該列表,如下所示:
public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
// Create a ViewModel the first time the system calls an activity's onCreate() method.
// Re-created activities receive the same MyViewModel instance created by the first activity.
MyViewModel model = new ViewModelProvider(this).get(MyViewModel.class);
model.getUsers().observe(this, users -> {
// update UI
});
}
}
ViewModel在 Fragment 之間共享數(shù)據(jù)
使用 ViewModel 對象解決這一常見的難點。這兩個 Fragment 可以使用其 Activity 范圍共享 ViewModel 來處理此類通信
public class SharedViewModel extends ViewModel {
private final MutableLiveData<Item> selected = new MutableLiveData<Item>();
public void select(Item item) {
selected.setValue(item);
}
public LiveData<Item> getSelected() {
return selected;
}
}
//獲取 ViewModelProvider 時,會收到相同的 SharedViewModel 實例(其范圍限定為該 Activity)
public class MasterFragment extends Fragment {
private SharedViewModel model;
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//通過requireActivity() Fragment 會檢索包含它們的 Activity
model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
itemSelector.setOnClickListener(item -> {
model.select(item);
});
}
}
//獲取 ViewModelProvider 時,會收到相同的 SharedViewModel 實例(其范圍限定為該 Activity)
public class DetailFragment extends Fragment {
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//通過requireActivity() Fragment 會檢索包含它們的 Activity
SharedViewModel model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
model.getSelected().observe(getViewLifecycleOwner(), { item ->
// Update the UI.
});
}
}
該方法的優(yōu)勢:
- Activity 不需要執(zhí)行任何操作,也不需要對此通信有任何了解。
- 除了 SharedViewModel 約定之外,F(xiàn)ragment 不需要相互了解。如果其中一個 Fragment 消失,另一個 Fragment 將繼續(xù)照常工作。
- 每個 Fragment 都有自己的生命周期,而不受另一個 Fragment 的生命周期的影響。如果一個 Fragment 替換另一個 Fragment,界面將繼續(xù)工作而沒有任何問題。
使用 LiveData 對象
官網(wǎng)使用參考
1、創(chuàng)建 LiveData 對象
LiveData 是一種可用于任何數(shù)據(jù)的封裝容器,其中包括可實現(xiàn) Collections 的對象,如 List。LiveData 對象通常存儲在 ViewModel 對象中,并可通過 getter 方法進(jìn)行訪問,如以下示例中所示:
public class NameViewModel extends ViewModel {
// Create a LiveData with a String
private MutableLiveData<String> currentName;
public MutableLiveData<String> getCurrentName() {
if (currentName == null) {
currentName = new MutableLiveData<String>();
}
return currentName;
}
// Rest of the ViewModel...
}
最初,LiveData 對象中的數(shù)據(jù)并未經(jīng)過設(shè)置。
注意:請確保用于更新界面的 LiveData 對象存儲在 ViewModel 對象中,而不是將其存儲在 Activity 或 Fragment 中,原因如下:
1、避免 Activity 和 Fragment 過于龐大。現(xiàn)在,這些界面控制器負(fù)責(zé)顯示數(shù)據(jù),但不負(fù)責(zé)存儲數(shù)據(jù)狀態(tài)。
2、將 LiveData 實例與特定的 Activity 或 Fragment 實例分離開,并使 LiveData 對象在配置更改后繼續(xù)存在。
2、觀察 LiveData 對象
在大多數(shù)情況下,在應(yīng)用組件的 onCreate() 方法是開始觀察 LiveData 對象原因如下:
1、確保系統(tǒng)不會從 Activity 或 Fragment 的 onResume() 方法進(jìn)行冗余調(diào)用。
2、確保 Activity 或 Fragment 變?yōu)榛钴S狀態(tài)后具有可以立即顯示的數(shù)據(jù)。一旦應(yīng)用組件處于 STARTED 狀態(tài),就會從它正在觀察的 LiveData 對象接收最新值。只有在設(shè)置了要觀察的 LiveData 對象時,才會發(fā)生這種情況。
LiveData 僅在數(shù)據(jù)發(fā)生更改時才發(fā)送更新,并且僅發(fā)送給活躍觀察者。此行為的一種例外情況是,觀察者從非活躍狀態(tài)更改為活躍狀態(tài)時也會收到更新。此外,如果觀察者第二次從非活躍狀態(tài)更改為活躍狀態(tài),則只有在自上次變?yōu)榛钴S狀態(tài)以來值發(fā)生了更改時,它才會收到更新。
以下示例代碼說明了如何開始觀察 LiveData 對象:
public class NameActivity extends AppCompatActivity {
private NameViewModel model;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Other code to setup the activity...
// Get the ViewModel.
model = new ViewModelProvider(this).get(NameViewModel.class);
// Create the observer which updates the UI.
final Observer<String> nameObserver = new Observer<String>() {
@Override
public void onChanged(@Nullable final String newName) {
// Update the UI, in this case, a TextView.
nameTextView.setText(newName);
}
};
// Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
model.getCurrentName().observe(this, nameObserver);
}
}
3、更新 LiveData 對象
LiveData 沒有公開可用的方法來更新存儲的數(shù)據(jù)。MutableLiveData 類將公開 setValue(T) 和 postValue(T) 方法,如果您需要修改存儲在 LiveData 對象中的值,則必須使用這些方法。通常情況下會在 ViewModel 中使用 MutableLiveData,然后 ViewModel 只會向觀察者公開不可變的 LiveData 對象。
設(shè)置觀察者關(guān)系后,您可以更新 LiveData 對象的值(如以下示例中所示),這樣當(dāng)用戶點按某個按鈕時會觸發(fā)所有觀察者:
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String anotherName = "John Doe";
model.getCurrentName().setValue(anotherName);
}
});
注意:
您必須調(diào)用 setValue(T) 方法以從主線程更新 LiveData 對象。
如果在 worker 線程中執(zhí)行代碼,則您可以改用 postValue(T) 方法來更新 LiveData 對象。
3、Data Binding
Data Binding是一種支持庫,借助該庫,您可以使用聲明性格式(而非程序化地)將布局中的界面組件綁定到應(yīng)用中的數(shù)據(jù)源。

專欄
Spring Cloud Alibaba微服務(wù)實戰(zhàn)
作者:猿芯
36幣
68人已購
查看
布局通常是使用調(diào)用界面框架方法的代碼在 Activity 中定義的。例如,以下代碼調(diào)用 findViewById() 來查找 TextView 控件并將其綁定到 viewModel 變量的 userName 屬性:
TextView textView = findViewById(R.id.sample_text);
textView.setText(viewModel.getUserName());
以下示例展示了如何在布局文件中使用Data Binding 將文本直接分配到TextView。這樣就無需調(diào)用上述任何 Java 代碼。請注意賦值表達(dá)式中 @{} 語法的使用:
<TextView
android:text="@{viewmodel.userName}" />
注意:
如果您使用Data Biding的主要目的是取代 findViewById() 調(diào)用,請考慮改用ViewBinding。
使用過ButterKnife的都知道,目前ButterKnife作者建議切換至ViewBindng使用;在許多情況下,ViewBinding可簡化實現(xiàn),提高性能,提供與DataBinding相同的好處。
Data Binding使用場景:
布局和綁定表達(dá)式
數(shù)據(jù)綁定的布局以根標(biāo)記 layout 開頭,后跟 data 元素和 view 根元素。如下:
注意:布局表達(dá)式應(yīng)保持精簡,因為它們無法進(jìn)行單元測試,并且擁有的 IDE 支持也有限。為了簡化布局表達(dá)式,可以使用自定義綁定適配器。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<!--data 中的 user 變量描述了可在此布局中使用的屬性。 -->
<data>
<variable name="user" type="com.example.User"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--布局中的表達(dá)式使用“@{}”語法給控件賦值。-->
<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>
系統(tǒng)會為每個布局文件生成一個綁定類。
1、默認(rèn)情況下,類名稱基于布局文件的名稱,它會轉(zhuǎn)換為駝峰形式并在末尾添加 Binding 后綴。
2、以上布局文件名為 activity_main.xml,因此生成的對應(yīng)類為 ActivityMainBinding,且都是ViewDataBinding的子類,所有布局對應(yīng)的生成的綁定類都可以是ViewDataBinding類
3、此類包含從布局屬性(例如,user 變量)到布局視圖的所有綁定,并且知道如何為綁定表達(dá)式指定值。
4、建議的綁定創(chuàng)建方法是在擴(kuò)充布局時創(chuàng)建,如以下示例所示:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
User user = new User("Test", "User");
binding.setUser(user);
}
a、Activity 數(shù)據(jù)綁定 ( DataBinding ) :
1、DataBindingUtil類方法:
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
2、生成的布局綁定類的inflate()方法:
ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//DataBindingUtil類方法
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
//生成的布局綁定類的inflate()方法
//ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
User user = new User("Test", "User");
binding.setUser(user);
}
b、 Fragment、ListView 或 RecyclerView 適配器中使用數(shù)據(jù)綁定 ( DataBinding )
DataBindingUtil 或 生成的布局綁定類deinflate() 方法,如以下代碼示例所示:
ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
// or
ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);
Data Binding綁定表達(dá)式:
xml里支持使用以下表達(dá)式:
- 算術(shù)運(yùn)算符 + - / * %
- 字符串連接運(yùn)算符 +
- 邏輯運(yùn)算符 && ||
- 二元運(yùn)算符 & | ^
- 一元運(yùn)算符 + - ! ~
- 移位運(yùn)算符 >> >>> <<
- 比較運(yùn)算符 == > < >= <=(請注意,< 需要轉(zhuǎn)義為 <)
- instanceof
- 分組運(yùn)算符 ()
- 字面量運(yùn)算符 - 字符、字符串、數(shù)字、null
- 類型轉(zhuǎn)換
- 方法調(diào)用
- 字段訪問
- 數(shù)組訪問 []
- 三元運(yùn)算符 ?:
不支持以下表達(dá)式:
- this
- super
- new
- 顯式泛型調(diào)用
a、變量
1、生成的數(shù)據(jù)綁定代碼會自動檢查有沒有 null 值并避免出現(xiàn) Null 指針異常。
2、例如,在表達(dá)式 @{user.name} 中,如果 user 為 Null,則為 user.name 分配默認(rèn)值 null。
3、如果您引用 user.age,其中 age 的類型為 int,則數(shù)據(jù)綁定使用默認(rèn)值 0。
<!--變量給控件賦值-->
android:text="@{user.name}"
<!--控件給變量賦值(雙向綁定)-->
android:text="@={user.name}"
b、Null 合并運(yùn)算符(空運(yùn)算符)
如果左邊運(yùn)算數(shù)不是 null,則 Null 合并運(yùn)算符 (??) 選擇左邊運(yùn)算數(shù),如果左邊運(yùn)算數(shù)為 null,則選擇右邊運(yùn)算數(shù)。
android:text="@{user.displayName ?? user.lastName}"
//等效于如下三目表達(dá)式
android:text="@{user.displayName != null ? user.displayName : user.lastName}"
c、視圖引用
1、表達(dá)式可以通過以下語法按 ID 引用布局中的其他視圖:
2、綁定類將 ID 轉(zhuǎn)換為駝峰式大小寫。
3、在以下示例中,TextView 視圖引用同一布局中的 EditText 視圖:android:text="@{exampleText.text}"
<EditText
android:id="@+id/example_text"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>
<TextView
android:id="@+id/example_output"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{exampleText.text}"/>
d、顯示隱藏控制
1、首先在 xml 的 data 節(jié)點中引用View
2、然后設(shè)置visibility
<data>
<import type="android.view.View"/>
</data>
android:visibility="@{student.boy ? View.VISIBLE : View.INVISIBLE}"
e、事件處理
方法引用:
android:onClick="@{handlers::onClickFriend}"
綁定表達(dá)式可將視圖的點擊監(jiān)聽器分配給MyHandlers 類的 onClickFriend() 方法,如下所示:
public class MyHandlers {
public void onClickFriend(View view) { ... }
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="handlers" type="com.example.MyHandlers"/>
<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}"
android:onClick="@{handlers::onClickFriend}"/>
</LinearLayout>
</layout>
注意:
1、在表達(dá)式中,您可以引用符合監(jiān)聽器方法簽名的方法。
2、當(dāng)表達(dá)式求值結(jié)果為方法引用時,數(shù)據(jù)綁定會將方法引用和所有者對象封裝到監(jiān)聽器中,并在目標(biāo)視圖上設(shè)置該監(jiān)聽器。
3、如果表達(dá)式的求值結(jié)果為 null,則數(shù)據(jù)綁定不會創(chuàng)建監(jiān)聽器,而是設(shè)置 null 監(jiān)聽器。
4、表達(dá)式中的方法簽名必須與監(jiān)聽器對象中的方法簽名完全一致。
監(jiān)聽器綁定:
android:onClick="@{() -> presenter.onSaveClick(task)}"
綁定表達(dá)式可將視圖的點擊事件綁定打給Presenter 類的 onSaveClick(Task task) 方法,如下所示:
public class Presenter {
public void onSaveClick(Task task){}
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="task" type="com.android.example.Task" />
<variable name="presenter" type="com.android.example.Presenter" />
</data>
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent">
<Button android:layout_width="wrap_content" android:layout_height="wrap_content"
android:onClick="@{() -> presenter.onSaveClick(task)}" />
</LinearLayout>
</layout>
以上,我們尚未定義傳遞給 onClick(View) 的 view 參數(shù)。
監(jiān)聽器綁定提供兩個監(jiān)聽器參數(shù)選項:您可以忽略方法的所有參數(shù),也可以命名所有參數(shù)。
如果您想命名參數(shù),則可以在表達(dá)式中使用這些參數(shù)。
例如,上面的表達(dá)式可以寫成如下形式:
android:onClick="@{(view) -> presenter.onSaveClick(task)}"
或者,如果您想在表達(dá)式中使用參數(shù),則采用如下形式:
public class Presenter {
public void onSaveClick(View view, Task task){}
}
android:onClick="@{(theView) -> presenter.onSaveClick(theView, task)}"
監(jiān)聽長按事件,表達(dá)式應(yīng)返回一個布爾值。
public class Presenter {
public boolean onLongClick(View view, Task task) { }
}
android:onLongClick="@{(theView) -> presenter.onLongClick(theView, task)}"
注意:
1、監(jiān)聽器綁定這些是在事件發(fā)生時進(jìn)行求值的 lambda 表達(dá)式。
2、數(shù)據(jù)綁定始終會創(chuàng)建一個要在視圖上設(shè)置的監(jiān)聽器。
3、事件被分派后,監(jiān)聽器會對 lambda 表達(dá)式進(jìn)行求值。
后臺私信回復(fù) 1024 免費(fèi)領(lǐng)取 SpringCloud、SpringBoot,微信小程序、Java面試、數(shù)據(jù)結(jié)構(gòu)、算法等全套視頻資料。






