android databinding使用教程

Android DataBinding 是一種可以將 UI 組件與數據源綁定的框架,能夠減少 findViewById 的使用,并提高代碼的可維護性。下面是 DataBinding 的完整使用教程:


1. 啟用 DataBinding

build.gradle(Module 級別)中啟用 DataBinding:

android {...buildFeatures {dataBinding true}
}

2. 創建布局文件

DataBinding 需要在 XML 布局文件的根標簽中使用 <layout> 作為根節點,并包含一個 <data> 標簽用于聲明變量。

示例:

<layout xmlns:android="http://schemas.android.com/apk/res/android"><data><variablename="user"type="com.example.User" /></data><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{user.name}" /><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Click Me"android:onClick="@{() -> user.onClickAction()}" /></LinearLayout>
</layout>
  • @{user.name} 直接綁定數據到 TextView。
  • @{() -> user.onClickAction()} 綁定點擊事件到方法。

3. 在 Activity/Fragment 中使用 DataBinding

在 Activity 或 Fragment 中使用 DataBinding 替代 findViewById

Activity 中使用

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import com.example.databindingexample.databinding.ActivityMainBinding;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);User user = new User("John Doe");binding.setUser(user);}
}

Fragment 中使用

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {FragmentExampleBinding binding = FragmentExampleBinding.inflate(inflater, container, false);User user = new User("Jane Doe");binding.setUser(user);return binding.getRoot();
}

4. 創建 Data Class

DataBinding 需要綁定的數據對象通常是一個 Java/Kotlin 類:

public class User {public String name;public User(String name) {this.name = name;}public void onClickAction() {Log.d("DataBinding", "Button Clicked!");}
}

如果想要數據動態更新,需要使用 Observable

import androidx.databinding.BaseObservable;
import androidx.databinding.Bindable;public class User extends BaseObservable {private String name;public User(String name) {this.name = name;}@Bindablepublic String getName() {return name;}public void setName(String name) {this.name = name;notifyPropertyChanged(BR.name);}
}

5. 雙向綁定

雙向綁定允許 UI 組件和數據對象之間互相影響,通常用于 EditText

<EditTextandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@={user.name}" />

注意 @=,這樣 UI 變化會自動更新 User.name,反之亦然。

User 類中:

import androidx.databinding.BaseObservable;
import androidx.databinding.Bindable;
import androidx.databinding.ObservableField;public class User {public final ObservableField<String> name = new ObservableField<>();
}

6. 使用 BindingAdapter 自定義屬性

創建 BindingAdapter 來擴展 DataBinding 的功能:

import android.widget.ImageView;
import androidx.databinding.BindingAdapter;
import com.bumptech.glide.Glide;public class ImageBindingAdapters {@BindingAdapter("imageUrl")public static void loadImage(ImageView view, String url) {Glide.with(view.getContext()).load(url).into(view);}
}

然后在 XML 中使用:

<ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"app:imageUrl="@{user.profileImageUrl}" />

總結

DataBinding 主要的優勢:

  • 減少 findViewById 的使用,提高代碼可讀性。
  • 支持數據綁定,可以直接在 XML 中綁定對象屬性。
  • 支持事件綁定,可在 XML 綁定點擊事件等邏輯。
  • 支持雙向綁定,簡化表單輸入處理。
  • 支持 BindingAdapter,可以擴展自定義屬性。

你可以試著把 DataBinding 和 ViewBinding 結合使用,在你的車載空調控制界面中優化 UI 交互邏輯!如果有具體的問題,比如如何在 Fragment 里使用,或者如何結合 LiveData,可以繼續問我。

dataBindingviewBinding 區別

  1. dataBinding true

    • 啟用 DataBinding,可以在 XML 布局文件中使用 <layout> 標簽,并支持數據綁定(@{} 表達式)。
    • 適用于 MVVM 架構,支持 雙向數據綁定事件綁定
    • 需要在代碼中使用 DataBindingUtil.setContentView()YourLayoutBinding.inflate() 獲取 binding 對象。
  2. viewBinding true

    • 啟用 ViewBinding,它只是一個 更簡單的方式來替代 findViewById,不會提供數據綁定能力。
    • 適用于 MVC/MVP 架構,只能直接訪問 XML 里的 View,沒有 @{} 這樣的綁定表達式。
    • 代碼使用 YourLayoutBinding.inflate() 獲取 binding 對象。

兩者是否可以共用?

可以!在 同一個項目同一個 Activity/Fragment 里,可以:

  • 對部分復雜頁面使用 DataBinding(比如動態 UI、MVVM 數據綁定)。
  • 對其他簡單頁面使用 ViewBinding(只用于 View 訪問)。

什么時候選 DataBinding,什么時候選 ViewBinding?

特性ViewBindingDataBinding
生成 Binding 類??
訪問 XML View??
省去 findViewById??
允許 @{} 綁定變量??
允許 @BindingAdapter 自定義屬性??
允許 @={} 雙向綁定??
代碼量多(但更強大)

如果只是簡化 findViewByIdViewBinding 足夠了。
如果需要數據綁定、LiveData、MVVM 等,DataBinding 是更好的選擇。

實際開發建議

  • 全局啟用 ViewBinding,作為默認的 View 訪問方式。
  • 僅在需要數據綁定的頁面啟用 DataBinding,這樣不會影響項目性能。

示例:

<!-- 使用 DataBinding 的 XML(需要 <layout> 標簽) -->
<layout xmlns:android="http://schemas.android.com/apk/res/android"><data><variable name="user" type="com.example.User" /></data><TextView android:text="@{user.name}" />
</layout>
<!-- 僅使用 ViewBinding(不需要 <layout> 標簽) -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"><TextView android:id="@+id/tvUserName" android:text="User Name" />
</LinearLayout>

在 Activity 中:

// DataBinding 方式
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setUser(new User("John Doe"));// ViewBinding 方式
ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
binding.tvUserName.setText("John Doe");

所以,你的 build.gradle 這樣寫 沒有問題,可以在不同的地方選擇合適的方式!

三 DataBinding 寫法歸納

Android DataBinding 中,XML 中的寫法主要可以歸納為以下幾種:


🌟 1. 變量綁定(@{變量名})

? 綁定普通對象

<TextView android:text="@{user.name}" />

📌 對應的變量

<variable name="user" type="com.example.User" />

? 綁定 LiveData

<TextView android:text="@{viewModel.userName}" />

📌 ViewModel 中 LiveData

val userName = MutableLiveData("張三")

📌 記得在 Fragment/Activity 設置

binding.lifecycleOwner = this

🌟 2. 事件綁定

? 綁定點擊事件

<Button android:onClick="@{() -> viewModel.onClick()}" />

📌 ViewModel 方法

fun onClick() {Log.d("DataBinding", "按鈕被點擊")
}

? 事件帶參數

<Button android:onClick="@{(view) -> viewModel.onClick(view)}"/>

📌 ViewModel 方法

fun onClick(view: View) {Toast.makeText(view.context, "按鈕點擊了!", Toast.LENGTH_SHORT).show()
}

🌟 3. 表達式運算

DataBinding 允許在 XML 直接寫 Java 表達式,比如:

<TextView android:text="@{user.age > 18 ? `成年人` : `未成年`}" />
<TextView android:text="@{String.valueOf(user.age)}" />

🌟 4. 方法調用

? 直接調用方法

<TextView android:text="@{user.getDisplayName()}" />

📌 對應的方法

fun getDisplayName(): String {return "$name ($age 歲)"
}

🌟 5. 雙向綁定(@={})

? EditText 雙向綁定

<EditText android:text="@={viewModel.userName}" />

📌 ViewModel

val userName = MutableLiveData("張三")

🚀 輸入框修改后,LiveData 里的值會自動更新


🌟 6. 資源綁定

? 綁定字符串資源

<TextView android:text="@{@string/app_name}" />

? 綁定顏色資源

<TextView android:textColor="@{@color/black}" />

🌟 7. 可見性控制

<TextView android:visibility="@{viewModel.isVisible ? View.VISIBLE : View.GONE}" />

📌 ViewModel

val isVisible = MutableLiveData(true)

🌟 8. RecyclerView 綁定(高級用法)

<androidx.recyclerview.widget.RecyclerViewapp:items="@{viewModel.userList}" />

需要自定義 BindingAdapter

@BindingAdapter("items")
fun bindRecyclerView(recyclerView: RecyclerView, items: List<User>?) {(recyclerView.adapter as? UserAdapter)?.submitList(items)
}

🌟 9. Fragment & Activity 綁定

val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
val binding = FragmentExampleBinding.inflate(inflater, container, false)

🌟 總結

類別寫法示例
變量綁定android:text="@{user.name}"
事件綁定android:onClick="@{() -> viewModel.onClick()}"
表達式android:text="@{user.age > 18 ? 成年人:未成年}"
方法調用android:text="@{user.getDisplayName()}"
雙向綁定android:text="@={viewModel.userName}"
資源綁定android:textColor="@{@color/black}"
可見性控制android:visibility="@{viewModel.isVisible ? View.VISIBLE : View.GONE}"
RecyclerView 綁定app:items="@{viewModel.userList}"

如果車載空調界面有溫度、風速的輸入框,可以直接用 @={} 綁定數據,省去 setText()

三 兩個setFanImage的含義

你的代碼確實涉及了兩部分的 setFanImage 方法,但它們的作用完全不同,并不是重復的。我們來詳細分析它們的區別和工作原理。


1. setFanImage()(ViewModel 內部的方法)

fun setFanImage() {val currentIndex = _fanImageIndex.value ?: 0val nextIndex = (currentIndex + 1) % 5_fanImageIndex.value = nextIndexTimber.d("setFanImage: $nextIndex")
}

作用

  • 這個方法 用于改變 _fanImageIndex 的值,即更新風扇狀態的索引。
  • _fanImageIndex 可能是 LiveData<Int>,一旦其值變化,綁定到它的 UI 組件就會自動更新。

2. setFanImage(imageView: ImageView, index: Int?)(BindingAdapter)

@JvmStatic
@BindingAdapter("fanImageResource")
fun setFanImage(imageView: ImageView, index: Int?) {index?.let {val resourceId = when (it) {0 -> R.drawable.ic_ac_fan_01 -> R.drawable.ic_ac_fan_12 -> R.drawable.ic_ac_fan_23 -> R.drawable.ic_ac_fan_34 -> R.drawable.ic_ac_fanelse -> R.drawable.ic_ac_fan_0}imageView.setImageResource(resourceId)}
}

作用

  • 這個方法 是一個 BindingAdapter,用于在 XML 綁定時,將 index 值轉換成具體的 ImageView 資源。
  • 它的作用是在 XML 布局文件中使用自定義的 fanImageResource 屬性,例如:

- 當 `viewModel.fanImageIndex` 發生變化時,這個 `BindingAdapter` 方法會被自動調用,為 `ImageView` 設置對應的風扇圖片。---### **為什么需要兩個 `setFanImage` 方法?**
1. **第一個 `setFanImage()` 方法**(ViewModel 方法)是 **業務邏輯**,用于更新風扇狀態的索引值 (`LiveData`)。
2. **第二個 `setFanImage()` 方法**(`BindingAdapter`)是 **UI 邏輯**,用于根據索引值更新 `ImageView` 的圖片。兩者雖然名字一樣,但功能完全不同:
- **ViewModel 方法負責數據更新**
- **BindingAdapter 負責 UI 綁定**,**當fanImageIndex改變后,更新imageView**這也是 DataBinding 的核心思想:**讓 UI 監聽數據變化,而不是手動在代碼中更新 UI**。---### **如何優化?**
如果你覺得方法名相同容易混淆,可以稍微修改命名,讓其更加清晰:
```kotlin
// ViewModel 里的方法
fun updateFanSpeedImage() {val currentIndex = _fanImageIndex.value ?: 0val nextIndex = (currentIndex + 1) % 5_fanImageIndex.value = nextIndex
}// BindingAdapter 方法
@JvmStatic
@BindingAdapter("fanImageResource")
fun bindFanImage(imageView: ImageView, index: Int?) {index?.let {val resourceId = when (it) {0 -> R.drawable.ic_ac_fan_01 -> R.drawable.ic_ac_fan_12 -> R.drawable.ic_ac_fan_23 -> R.drawable.ic_ac_fan_34 -> R.drawable.ic_ac_fanelse -> R.drawable.ic_ac_fan_0}imageView.setImageResource(resourceId)}
}

這樣方法名更具描述性,減少混淆。


總結

你并沒有寫重復的方法,而是分別:

  1. 在 ViewModel 里寫了數據變化邏輯(修改風扇索引)。
  2. BindingAdapter 里寫了 UI 綁定邏輯(根據索引更改 ImageView)。

這是 DataBinding 典型的 MVVM 設計模式,可以提高代碼的清晰度和可維護性。

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

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

相關文章

python如何快速刪除文件夾中的大量文件

在 Python 中&#xff0c;刪除文件夾中的大量小圖片文件可以通過使用 os 模塊或 shutil 模塊來實現。以下是一個示例代碼&#xff0c;展示了如何快速刪除指定文件夾中的所有文件。如果你只需要刪除小圖片文件&#xff0c;可以添加額外的邏輯來檢查文件大小。 以下是一個示例代…

如何使用 IntelliJ IDEA 開發命令行程序(或 Swing 程序)并手動管理依賴(不使用 pom.xml)

以下是詳細步驟&#xff1a; 1. 創建項目 1.1 打開 IntelliJ IDEA。 1.2 在啟動界面&#xff0c;點擊 Create New Project&#xff08;創建新項目&#xff09;。 1.3 選擇 Java&#xff0c;然后點擊 Next。 1.4 確保 Project SDK 選擇了正確的 JDK 版本&#x…

FastAPI-Cache2: 高效Python緩存庫

FastAPI-Cache2是一個強大而靈活的Python緩存庫&#xff0c;專為提升應用性能而設計。雖然其名稱暗示與FastAPI框架的緊密集成&#xff0c;但實際上它可以在任何Python項目中使用&#xff0c;為開發者提供簡單而高效的緩存解決方案。 在現代應用開發中&#xff0c;性能優化至關…

android開發:zxing-android-embedded豎屏掃描功能

Android 點擊按鈕調用豎屏二維碼掃描 提示&#xff1a;zxing-android-embedded插件已過時&#xff0c;建議更換別的。 場景&#xff1a;Home頁面上有個掃描按鈕&#xff0c;點擊后打開攝像頭完成掃描功能&#xff0c;掃描時要求豎屏。 方案&#xff1a;使用zxing-android-embe…

指令補充+樣式綁定+計算屬性+監聽器

一、指令補充 1. 指令修飾符 1. 作用: 借助指令修飾符, 可以讓指令更加強大 2. 分類: 1> 按鍵修飾符: 用來檢測用戶的按鍵, 配合鍵盤事件使用. keydown 和 keyup 語法: keydown.enter/v-on:keydown.enter 表示當enter按下的時候觸發 keyup.enter/v-on:keyup.enter 表示當…

Python基于時間序列分析的降雨量預測系統的設計與實現【附源碼、文檔說明】

博主介紹&#xff1a;?Java老徐、7年大廠程序員經歷。全網粉絲12w、csdn博客專家、掘金/華為云/阿里云/InfoQ等平臺優質作者、專注于Java技術領域和畢業項目實戰? &#x1f345;文末獲取源碼聯系&#x1f345; &#x1f447;&#x1f3fb; 精彩專欄推薦訂閱&#x1f447;&…

【2022】【論文筆記】基于相變材料的光學激活的、用于THz光束操作的編碼超表面——

前言 類型 太赫茲 + 超表面 太赫茲 + 超表面 太赫茲+超表面 期刊 A D V A N C E D ?? O P T I C A L ?? M A T E R I A L S ADVANCED \; OPTICAL \; MATERIALS

[VolgaCTF 2025] Baby-Welcome,BrokeBroke,Field Rules

這個就做了倆題&#xff0c;其實再努力點就是3個。不過最近也算是好成績了&#xff0c;45名。國外的比賽對我來說還算是比較難的。 Baby-Welcome 這個流程還挺麻煩&#xff0c;先是注冊用戶&#xff0c;登錄的用戶可以給其它用戶發消息。收到消息的用戶可以顯示消息&#xff…

再見VS Code!Google IDE 正顛覆傳統開發體驗

云端開發的革命&#xff1a;Google Project IDX 如何顛覆傳統開發體驗 在軟件開發領域&#xff0c;Google 最新推出的 Project IDX 絕非僅僅是另一個“基于瀏覽器的 VS Code”——它是一次真正的范式轉變。與 VS Code、Cursor 等傳統工具不同&#xff0c;IDX 是一個完全云原生的…

NLP高頻面試題(三十六)——深入理解思維鏈(Chain-of-Thought)提示方法

一、什么是思維鏈提示&#xff08;CoT&#xff09;&#xff1f; 思維鏈提示是一種新穎的提示方法&#xff0c;通過向模型提供少量的推理步驟示范&#xff0c;讓語言模型在給出最終答案之前展示出自己的推理過程。其核心思想在于鼓勵模型模仿人類逐步推理的方式&#xff0c;從而…

探索新一代大模型代理(LLM agent)及其架構

在人工智能大模型(AI)的浪潮中&#xff0c;2023年我們見證了檢索增強生成(Retrieval Augmented Generation, RAG)的興起&#xff0c;而2024年則無疑成為了“代理”agent的元年。各大AI企業紛紛投身于聊天機器人代理的研發中&#xff0c;工具如MultiOn通過與外部網站的連接實現了…

26考研——線性表_ 線性表的鏈式表示_雙循環鏈表(2)

408答疑 文章目錄 三、 線性表的鏈式表示雙循環鏈表單鏈表與雙鏈表的比較單鏈表的特點雙鏈表的特點 雙鏈表上基本操作的實現雙鏈表的插入操作雙鏈表的刪除操作 雙鏈表的代碼實操定義結點創建一個結點帶頭結點的雙鏈表初始化創建雙鏈表打印雙鏈表查找結點插入結點在指定節點后插…

【備忘】在Docker中安裝寶塔面板,實現環境隔離,又能快速遷移服務器環境

我的環境是阿里云服務器&#xff08;新環境&#xff09; 【待繼續】 【新方法】 我已經安裝了docker&#xff0c;所以這里我先卸載。 卸載命令&#xff1a; sudo yum remove docker* containerd.io -y Docker默認保存位置是/var/lib/docker/&#xff0c;卸載Docker時&#x…

池化技術的深度解析與實踐指南【大模型總結】

池化技術的深度解析與實踐指南 池化技術作為計算機系統中的核心優化手段&#xff0c;通過資源復用和預分配機制顯著提升系統性能。本文將從原理、實現到最佳實踐&#xff0c;全方位剖析池化技術的核心要點&#xff0c;并結合實際案例說明其應用場景與調優策略。 一、池化技術的…

HCIP【BGP協議(詳解)】

目錄 1 BGP協議產生背景 2 BGP協議特性 2.1 自治系統間路由傳播 2.2 路由矢量協議 2.3 防環機制 2.4 基于TCP傳輸 2.5 路由更新機制 2.6 豐富的路由屬性 2.7 支持CIDR和路由聚合 2.8 路由過濾和策略控制 2.9 動態對等體功能 3 BGP基本術語 4 BGP規劃問題 4.1 路…

VirtualBox 配置雙網卡(NAT + 橋接)詳細步驟

在 VirtualBox 中為 CentOS 虛擬機配置雙網卡&#xff08;NAT 橋接&#xff09;&#xff0c;使其既能訪問外網&#xff08;NAT&#xff09;&#xff0c;又能與宿主機&#xff08;Windows 10&#xff09;或局域網通信&#xff08;橋接&#xff09;。 步驟 1&#xff1a;關閉虛…

Upload-labs靶場通關

之前搭好了靶場&#xff0c;Upload-labs 靶場搭建 及一句話木馬的原理與運用-CSDN博客 今天開始通關并寫詳細流程 Pass-1 來到靶場的第一關 先隨便上傳php 代碼 點擊上傳 發現文件類型被限制了 方法1&#xff1a; 改文件后綴為合法文件&#xff08;.jpg .png .gif&#xf…

[GN] Python3基本數據類型 -- 與C的差異

Python3 面向對象 文章目錄 Python3的基本數據類型6個標準的數據類型NumbersStringListtupleSetsDictionaries Python運算符邏輯 運算符成員運算符身份運算符 Python3 數字Python3 序列序列切片序列相加序列相乘序列相關內置函數 Python3 列表訪問列表的值更新列表刪除列表元素…

MCP over MQTT:EMQX 開啟物聯網 Agentic 時代

前言 隨著 DeepSeek 等大語言模型&#xff08;LLM&#xff09;的廣泛應用&#xff0c;如何找到合適的場景&#xff0c;并基于這些大模型構建服務于各行各業的智能體成為關鍵課題。在社區中&#xff0c;支持智能體開發的基礎設施和工具層出不窮&#xff0c;其中&#xff0c;Ant…

AI助力高效PPT制作:從內容生成到設計優化

隨著人工智能技術的不斷發展&#xff0c;AI在各個領域的應用日益普及&#xff0c;尤其是在文檔和演示文稿的創建過程中。PowerPoint&#xff08;PPT&#xff09;作為最常用的演示工具之一&#xff0c;借助AI的技術手段&#xff0c;可以極大地提高制作效率并提升最終呈現效果。在…