ViewBinding vs DataBinding 深度对比
选择最适合你的视图绑定方案
目录
两者概述
ViewBinding 用法
DataBinding 用法
功能对比
性能对比
选择建议
1. 两者概述
flowchart LR
subgraph VB["ViewBinding (2019)"]
VB1["只生成绑定类,不修改布局文件"]
VB2["只读的单向绑定"]
VB3["无需额外运行时开销"]
VB4["不支持 XML 表达式"]
end
subgraph DB["DataBinding (2015)"]
DB1["生成绑定类 + 修改布局文件"]
DB2["支持双向绑定 (@={})"]
DB3["支持 XML 表达式和事件处理"]
DB4["有运行时开销"]
end
2. ViewBinding 用法 启用 1 2 3 4 5 6 7 8 android { buildFeatures { viewBinding { enabled = true } } }
基本使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/tvTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:id="@+id/btnClick" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> class MainActivity : AppCompatActivity () { private lateinit var binding: ActivityMainBinding override fun onCreate (savedInstanceState: Bundle ?) { super .onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) binding.tvTitle.text = "Hello ViewBinding" binding.btnClick.setOnClickListener { } } }
Fragment 中使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class MyFragment : Fragment () { private var _binding: FragmentMyBinding? = null private val binding get () = _binding!! override fun onCreateView ( inflater: LayoutInflater , container: ViewGroup ?, savedInstanceState: Bundle ? ) : View { _binding = FragmentMyBinding.inflate(inflater, container, false ) return binding.root } override fun onViewCreated (view: View , savedInstanceState: Bundle ?) { super .onViewCreated(view, savedInstanceState) binding.tvTitle.text = "Hello" } override fun onDestroyView () { super .onDestroyView() _binding = null } }
3. DataBinding 用法 启用 1 2 3 4 5 6 android { dataBinding { enabled = true } }
布局文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <layout xmlns:android ="http://schemas.android.com/apk/res/android" > <data > <variable name ="user" type ="com.example.User" /> <variable name ="viewModel" type ="com.example.MainViewModel" /> </data > <LinearLayout android:layout_width ="match_parent" android:layout_height ="match_parent" android:orientation ="vertical" > <TextView android:text ="@{user.name}" /> <EditText android:text ="@={user.email}" /> <Button android:onClick ="@{() -> viewModel.onButtonClick()}" /> </LinearLayout > </layout >
Activity 使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class MainActivity : AppCompatActivity () { private lateinit var binding: ActivityMainBinding override fun onCreate (savedInstanceState: Bundle ?) { super .onCreate(savedInstanceState) binding = DataBindingUtil.setContentView(this , R.layout.activity_main) val user = User("John" , "john@example.com" ) binding.user = user binding.lifecycleOwner = this binding.viewModel = viewModel } }
XML 表达式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 android:text="@{`Hello ` + user.name}" android:text="@{viewModel.getDisplayName(user)}" android:text="@{user.name ?? `Default`}" android:text="@string/app_name" android:textColor="@{isError ? @color/red : @color/black}"
4. 功能对比 功能对比表
功能
ViewBinding
DataBinding
代码生成
✅
✅
布局修改
❌
✅ 需要 <layout>
单向绑定
✅
✅
双向绑定
❌
✅ (@={})
XML 表达式
❌
✅
事件绑定
❌
✅
自定义 Binding
❌
✅
Observable 字段
❌
✅
编译检查
部分
✅ 完整
双向绑定 1 2 3 4 5 6 7 8 <EditText android:text="@={user.name}" /> user.name = "New Name"
自定义 Binding 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class BindingAdapters { @JvmStatic @BindingAdapter("imageUrl" ) fun loadImage (view: ImageView , url: String ?) { url?.let { Glide.with(view.context).load(it).into(view) } } @JvmStatic @BindingAdapter("visible" ) fun setVisible (view: View , visible: Boolean ) { view.visibility = if (visible) View.VISIBLE else View.GONE } @JvmStatic @BindingAdapter("onSearch" ) fun setSearchListener (view: EditText , listener: (String ) -> Unit ) { view.setOnEditorActionListener { _, _, _ -> listener(view.text.toString()) true } } } <ImageView app:imageUrl="@{user.avatarUrl}" app:visible="@{!user.avatarUrl.isEmpty()}" />
5. 性能对比 性能差异
flowchart LR
VBPerf["ViewBinding"] --> VBP1["编译时生成绑定类"]
VBPerf --> VBP2["运行时开销: 0"]
VBPerf --> VBP3["内存: 只有 View 引用"]
VBPerf --> VBP4["编译速度: 快"]
DBPerf["DataBinding"] --> DBP1["编译时生成绑定类 + 额外代码"]
DBPerf --> DBP2["运行时开销: 观察者模式"]
DBPerf --> DBP3["内存: View + Data + Observer"]
DBPerf --> DBP4["编译速度: 慢(需处理表达式)"]
Conclusion["结论"] --> Better["ViewBinding 性能更好"]
编译时间影响 1 2 3 4 5 ./gradlew assembleDebug --profile
6. 选择建议 决策树
flowchart TD
Start["需要双向绑定?"] -->|是| DataBinding1["DataBinding"]
Start -->|否| Expr["需要 XML 表达式?"]
Expr -->|是| DataBinding2["DataBinding"]
Expr -->|否| Event["需要事件绑定?"]
Event -->|是| DataBinding3["DataBinding"]
Event -->|否| ViewBinding["ViewBinding(推荐)"]
实际建议
场景
推荐
简单列表展示
ViewBinding
表单输入
DataBinding
MVVM + LiveData
DataBinding
只需 View 引用
ViewBinding
追求性能
ViewBinding
复杂 UI 逻辑
DataBinding
混合使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 android { buildFeatures { viewBinding { enabled = true } dataBinding { enabled = true } } }
总结
flowchart TB
Choose["选择原则"] --> C1["简单页面 → ViewBinding(性能好)"]
Choose --> C2["复杂交互 → DataBinding(功能强)"]
Choose --> C3["MVVM 架构 → DataBinding"]
Choose --> C4["性能优先 → ViewBinding"]
相关文章 :