9.3 数据绑定表达式9.3.1 基本表达式常用表达式类型表达式类型示例说明属性访问{user.name}访问对象的属性方法调用{user.getName()}调用对象的方法字符串格式化{string/name_format(user.name)}使用字符串资源算术运算{user.age 1}算术运算逻辑运算{user.isAdult user.hasPermission}逻辑运算三元运算符{user.isAdult ? 成年 : 未成年}条件判断空合并{user.nickName ?? user.name}空值合并集合访问{user.addresses[0]}访问集合元素表达式示例datavariablenameusertypecom.example.app.model.User//data!-- 属性访问 --TextViewandroid:text{user.name}/!-- 方法调用 --TextViewandroid:text{user.getFullName()}/!-- 字符串格式化 --TextViewandroid:text{string/user_info(user.name, user.age)}/!-- 算术运算 --TextViewandroid:text{string/age_plus_one(user.age 1)}/!-- 逻辑运算 --TextViewandroid:visibility{user.isAdult user.hasPermission ? View.VISIBLE : View.GONE}/!-- 三元运算符 --TextViewandroid:text{user.isAdult ? 成年 : 未成年}/!-- 空合并 --TextViewandroid:text{user.nickName ?? user.name}/!-- 集合访问 --TextViewandroid:text{user.addresses[0].city}/9.3.2 字符串资源引用strings.xmlresourcesstringnamename_format姓名%s/stringstringnameage_format年龄%d/stringstringnameuser_info%s%d 岁/string/resources在布局中使用TextViewandroid:text{string/name_format(user.name)}/TextViewandroid:text{string/age_format(user.age)}/TextViewandroid:text{string/user_info(user.name, user.age)}/9.3.3 Import 语句Import 类dataimporttypeandroid.view.View/importtypeandroid.text.TextUtils/importtypecom.example.app.utils.StringUtils/importtypecom.example.app.model.UseraliasUserModel/variablenameusertypeUserModel//data!-- 使用导入的类 --TextViewandroid:visibility{TextUtils.isEmpty(user.name) ? View.GONE : View.VISIBLE}/TextViewandroid:text{StringUtils.formatUser(user)}/9.4 双向数据绑定9.4.1 双向绑定的概念单向绑定 vs 双向绑定类型数据流向说明单向绑定数据 → UI数据变化自动更新 UI双向绑定数据 ↔ UI数据变化更新 UIUI 变化也更新数据9.4.2 实现双向绑定方式1使用 Observable Field/** * 用户模型 */classUser:BaseObservable(){get:Bindablevarname:Stringset(value){fieldvaluenotifyPropertyChanged(BR.name)}get:Bindablevarage:Int0set(value){fieldvaluenotifyPropertyChanged(BR.age)}get:Bindablevaremail:Stringset(value){fieldvaluenotifyPropertyChanged(BR.email)}}datavariablenameusertypecom.example.app.model.User//data!-- 双向绑定 --EditTextandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:text{user.name}android:hint姓名/EditTextandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:text{user.age}android:hint年龄android:inputTypenumber/EditTextandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:text{user.email}android:hint邮箱android:inputTypetextEmailAddress/方式2使用 ObservableField/** * 用户模型 */classUser{valnameObservableFieldString()valageObservableFieldInt()valemailObservableFieldString()}/** * 用户 Activity */classUserActivity:AppCompatActivity(){privatelateinitvarbinding:ActivityUserBindingprivatelateinitvaruser:UseroverridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)bindingDataBindingUtil.setContentView(this,R.layout.activity_user)// 创建 User 对象userUser()user.name.set(张三)user.age.set(25)user.email.set(zhangsanexample.com)// 设置数据到绑定对象binding.useruser binding.lifecycleOwnerthis}}方式3使用 MutableLiveData/** * 用户 ViewModel */classUserViewModel:ViewModel(){privateval_userMutableLiveDataUser()valuser:LiveDataUser_userprivateval_nameMutableLiveDataString()valname:LiveDataString_nameprivateval_ageMutableLiveDataInt()valage:LiveDataInt_ageprivateval_emailMutableLiveDataString()valemail:LiveDataString_emailfunloadUser(userId:String){viewModelScope.launch{valuseruserRepository.getUser(userId)_user.valueuser _name.valueuser.name _age.valueuser.age _email.valueuser.email}}funupdateUser(){viewModelScope.launch{valuserUser(name_name.value?:,age_age.value?:0,email_email.value?:)userRepository.updateUser(user)}}}datavariablenameviewModeltypecom.example.app.viewmodel.UserViewModel//data!-- 双向绑定 --EditTextandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:text{viewModel.name}android:hint姓名/EditTextandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:text{viewModel.age}android:hint年龄android:inputTypenumber/EditTextandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:text{viewModel.email}android:hint邮箱android:inputTypetextEmailAddress/Buttonandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:text更新android:onClick{() - viewModel.updateUser()}/主要是databinding的表达式和双向绑定EditText。