DataBinding使用进阶

本文详细介绍Android中MVVM架构及DataBinding技术的应用,包括DataBinding如何简化UI编程,提高性能,以及其实现原理和使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

android原生支持MVVM-DataBinding

从2015年开始Android官方支持MVVM框架 
首先我们需要知道MVVM是什么? 
MVVM是从一种开发模式,不同于MVC和MVP,MVVM分为Model层、View层、和ViewModel层,MVVM最大的特点就是Model层和ViewModel层之间可以进行绑定,也就是说View可以对应着ViewModel

Google使用DataBinding来支持MVVM模型 
Data Binding 解决了 Android UI 编程中的一个痛点,官方原生支持 MVVM 模型可以让我们在不改变既有代码框架的前提下,非常容易地使用这些新特性

使用DataBinding进行MVVM开发 
DataBinding是2015年谷歌I/O上提出来的,从字面意思上看就是数据绑定,实际上就是将数据绑定在xml中,并实现及时刷新,听起来就碉堡了,再也没有了findviewbyId,虽然现在很多注解框架也能实现无findviewbyId,但是这样会影响性能,现在使用DataBinding就不需要这方面的考虑了

DataBinding技术能解决什么问题?

从开发角度看,简言之,DataBinding主要解决了两个问题:

1、需要多次使用findViewById,损害了应用性能且令人厌烦 
2、更新UI数据需切换至UI线程,将数据分解映射到各个view比较麻烦

但是应该说:针对上述问题,都有第三方解决方案。第一个问题可以使用ButterKnife;对于第二个问题,谷歌提供了Loop-Handler方案,你还可以使用RxJava,EventBus等方案,但它们只是解决了线程切换的问题,却没有解决将数据分解映射到各个view的问题,这正是DataBinding的魅力所在!同时,DataBinding的线程切换也是透明的,这是指,当你的Activity需要展示新的数据时,你可以在后台线程中获取数据,然后直接交给DataBinding就可以了,完全不需要关心线程切换的问题。

DataBinding的使用规则: 
使用 Data Binding 之后,xml的布局文件就不再单纯地展示 UI 元素,还需要定义 UI 元素用到的变量。所以,它的根节点不再是一个 ViewGroup,而是变成了 layout,并且新增了一个节点 data。

意思就是之前我们的布局文件就仅仅只是负责View的显示样式,一般来说不会涉及到任何和数据有关的东西,也就是说我们只会知道这个布局没有数据的时候回事什么样子的,但是加什么数据以及加上数据之后是什么样子我们完全不知道

<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
    `...
 </data>
<!--原先的根节点(Root Element)-->
<LinearLayout>
 ....
</LinearLayout>
</layout>

 

要实现 MVVM 的 ViewModel 就需要把数据与UI进行绑定,data 节点就为此提供了一个桥梁,我们先在 data 中声明一个 variable,这个变量会为 UI 元素提供数据(例如 TextView 的 android:text),然后在 Java 代码中把”后台”数据与这个 variable 进行绑定

我们知道在之前我们的布局文件中是不存在变量这个概念的,或者说我们的布局文件处理去获得Res资源文件中的数据之外是不可能主动获取数据的(除非在java代码中使用findViewById得到组件之后进行设置),而现在我们的布局不仅仅只是view了,而且还可以规定我们的view需要的数据,可以这样理解我们把布局文件进行了封装(类似接口),下载我们在布局中可以规定我们将会使用到的数据,

方法就是在根节点下面使用节点,声明一个变量,这里的type是用来定义这个变量的类型的,其作用就和你在java代码中使用 User xiaoming ;一样相当于是声明这个变量是什么类型的(当然名字这么长是因为使用过了自定义类的全类名),其中type属性就是我们在java文件中定义的数据bean类,如下:

<data>
<variable name="user" type="com.liangfeizc.databindingsamples.basic.User" />
</data>

 

当然我们也是可以类似java类里面一样使用导入的方式来缩短type的写法

<data>
 <import type="com.liangfeizc.databindingsamples.basic.User" />
<variable name="user" type="User" />
</data>

 

然后因为我们在 build.gradle 中设置了databinding = true,所以DataBinding会根据xml文件的名称 Generate 一个继承自 ViewDataBinding 的类。(怪不得是需要Google官方支持的,原来是以插件的形式,具体来说应该是gradle支持的)

例如,这里 xml 的文件名叫 activity_basic.xml,那么生成的类就是 ActivityBasicBinding

java.lang.* 包中的类会被自动导入,可以直接使用,例如要定义一个 String 类型的变量:(type不需要写全类名,但是其他类型的还是需要写全类名的)

<variable name="firstName" type="String" />

 

layout文件绑定 Variable

修改 BasicActivity 的 onCreate 方法,用 DatabindingUtil. setContentView()来替换掉 setContentView(),此方法会返回一个ActivityBasicBinding对象,此对象就是你在layout文件中定义了之后DataBinding自动生成的,然后创建一个 user 对象,通过 binding.setUser(user) 与 variable 进行绑定(上一篇:DataBinding-开始使用 中介绍过为什么需要这么做) 
http://blog.youkuaiyun.com/wang2963973852/article/details/70858527 
(厉害了如果不是官方的,谁能这么深入android的源码,搞出这样的东西?这个MVVM已经不向MVP一样仅仅只是一种编程思想了,已经升级到了一种工具和一种框架的层面了)

@Override
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
ActivityBasicBinding binding = DataBindingUtil.setContentView(
            this, R.layout.activity_basic);
             User user = new User("fei", "Liang");
         binding.setUser(user);

 

注意: 
需要注意的是DataBinding会根据布局文件来生成一个类,这个类的类名是根据你的布局文件的名字自动生成的,但是点击这个自动生成的类写的时候,却直接进入了我们设置的布局文件,这更说明了这个自动生成的类是根据这个布局文件生成的,但是我们还是想去这个类看看怎么办:在这里:把工程切换到project类型,ActivityxxxBinding在/app/build/intermediates/classes/debug/xxx/xxx/xxx/databinding下,注意如果找不到那是因为这是在编译的时候生成的,因此需要debug一下

注意: 
上面的ActivityBasicBinding 类是自动生成的,所有的 set 方法也是根据 variable 名称生成的。例如,我们定义了两个变量

<data>
    <variable name="firstName" type="String" />
    <variable name="lastName" type="String" />
</data>

 

那么就会在ActivityBasicBinding 类中对应的生成两个方法,

setFirstName(String firstName);
setLastName(String lastName);

 

为什么会生成上面两个方法,因为我们的ActivityBasicBinding 类是ViewModel,它不但持有view的引用而且持有model的引用,也就是说ActivityBasicBinding 里面不但有我们布局文件里面所有的组件的引用(解决了findViewById),而且有我们在layout中定义的变量的引用,这些引用都是以field的形式存在的

到这里我们的布局文件就正式的和我们的activity绑定了,而且我们在布局文件的《data》节点下定义的变量Variable也和我们对应的java数据bean类对象绑定了,

layout文件中使用 Variable

数据与 Variable 绑定之后,xml 的 UI 元素就可以直接使用了,如下:

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

 

上面我们在布局文件中的一个textView里面使用了我们在此布局文件中定义的lastName变量,这个变量的类型是String类型 
至此,一个简单的数据绑定就完成了

高级用法:(在XML文件中调用类方法)

首先假设我们在一个类里面定义了一个静态方法,如下:

 public class MyStringUtils {
    public static String capitalize(final String word) {
        return String.valueOf(word.charAt(0))+ word.substring(1); 
        }

 

然后在XML文件的节点中导入:

<import type="com.liangfeizc.databindingsamples.utils.MyStringUtils" />
<variable
            name="StringUtils"
            type="MyStringUtils"/>

 

使用起来和java语法一样:

<TextView
    android:layout_height="wrap_content"
    android:text="@{StringUtils.capitalize(user.firstName)}" />

 

如上:使用方法和调用java方法一样:就是使用类名调用方法并且传入参数,然后将方法返回值使用到text属性得值上面,

@{className.mothodName(mothodParam)

 

  • 1

但是需要注意的是: 
我们知道DataBinding是Android官方出的支持MVVM的框架,但是即便是这样Android也不可能因为要支持MVVM,就对之前定义的XML文件中的组件的属性的用法进行修改,那么就只有DataBinding去适应Android布局文件中组件属性的使用方式了

举个例子吧:就拿上面的《TextView》来说明,我们想要给TextView的text属性设置值,那么我们知道text属性需要的值是字符串,而我们的大括号里面的是DataBinding定义的表达式,DataBinding每次在读取Android组件的属性值的时候,需要去解析大括号里面的表达式,然后将解析出来的值赋值给Android组件的属性,也就是说我们我们使用表达式调用的方法的返回值一定要是组件属性需要的类型

<think>我们正在讨论高级Android开发技术。根据之前的对话历史,用户已经表达了对学习高级Android开发技巧的兴趣。我们需要提供结构清晰、内容可靠的回答,并生成相关问题。注意:回答中需要包含数学公式时,行内公式用$...$,独立公式用$$...$$并单独成段。同时,回答末尾需要生成相关问题。高级Android开发技术涵盖多个方面,包括性能优化、架构设计、安全性、响应式编程、测试等。以下将分步骤介绍一些关键的高级技术:1.**架构组件与设计模式**:-使用AndroidJetpack组件,特别是ViewModel、LiveData、Room和DataBinding,可以帮助构建健壮、可测试和可维护的应用。-推荐采用MVVM(Model-View-ViewModel)或MVI(Model-View-Intent)架构模式。这些模式有助于分离关注点,使代码更清晰。-例如,ViewModel的代码示例:```kotlinclassMyViewModel:ViewModel(){privateval_data=MutableLiveData<String>()valdata:LiveData<String>=_datafunloadData(){//执行异步操作,更新_data}}```2.**异步编程**:-使用Kotlin协程处理异步操作,避免回调地狱。协程提供了更简洁的方式来管理后台线程和耗时操作。-结合使用协程和LiveData,可以使用`liveData`构建器:```kotlinvaldata:LiveData<Result>=liveData{emit(Result.loading())try{emit(Result.success(fetchData()))}catch(e:Exception){emit(Result.error(e))}}```3.**性能优化**:-**内存优化**:避免内存泄漏,使用LeakCanary检测泄漏。注意Activity和Fragment的生命周期,及时取消注册监听器。-**启动优化**:应用启动分为冷启动、温启动和热启动。优化冷启动时间,可以通过减少主线程工作、延迟初始化等实现。-启动时间优化公式:启动时间$T$可以分解为$T=T_{\text{init}}+T_{\text{load}}+T_{\text{display}}}$,其中$T_{\text{init}}$是初始化时间,$T_{\text{load}}$是数据加载时间,$T_{\text{display}}$是显示时间[^1]。4.**安全性**:-防止二次打包和篡改:使用代码混淆(ProGuard或R8)、签名验证、加固技术(如加壳)等。参考站内引用中提到的加固技术[^1]。-存储安全:使用AndroidKeystore系统存储加密密钥,对敏感数据进行加密。-网络通信安全:使用HTTPS,并实现证书固定(CertificatePinning)。5.**响应式编程**:-使用RxJava或KotlinFlow处理数据流。KotlinFlow是协程的一部分,提供了一种冷流(coldstream)的响应式编程方式。-示例:使用Flow从网络加载数据并更新UI:```kotlinfunfetchData():Flow<Result>=flow{emit(Result.loading())try{valdata=apiService.getData()emit(Result.success(data))}catch(e:Exception){emit(Result.error(e))}}```6.**测试**:-单元测试:使用JUnit、Mockito等测试ViewModel和业务逻辑。-界面测试:使用Espresso进行界面交互测试。-使用依赖注入(如Hilt)可以更方便地替换测试依赖。7.**模块化与动态功能**:-将应用拆分为多个模块,按需加载(使用DynamicFeatureModules),可以减少初始下载大小。-使用PlayCore库实现动态功能模块的下载和安装。8.**JetpackCompose**:-现代UI工具包,使用声明式UI构建界面。学习Compose可以提升开发效率和UI灵活性。-示例Compose函数:```kotlin@ComposablefunGreeting(name:String){Text(text="Hello,$name!")}```9.**持续集成与交付(CI/CD)**:-配置CI/CD流程,例如使用Jenkins、GitHubActions或GitLabCI,自动化构建、测试和发布。以上是一些高级Android开发技术的概述。掌握这些技术将帮助你构建更高效、更安全、更易维护的Android应用。§§相关问题§§1.如何优化Android应用的内存使用?2.Kotlin协程与RxJava相比有哪些优势?3.在Android中如何实现安全的网络通信?4.JetpackCompose与传统XML布局相比有什么优势?5.如何设计一个模块化的Android应用?6.有哪些有效的Android应用加固方法?</think>### 高级Android开发技术详解 以下是需要掌握的高级Android开发核心技术,涵盖架构设计、性能优化、安全防护等方面: #### 1. **现代架构模式** - **MVVM/MVI架构** 使用`ViewModel` + `LiveData`/`StateFlow`实现数据持久化与UI解耦: ```kotlin class UserViewModel : ViewModel() { private val _userState = MutableStateFlow<UserState>(Loading) val userState: StateFlow<UserState> = _userState.asStateFlow() fun fetchUser() { viewModelScope.launch { _userState.value = Success(userRepository.getUser()) } } } ``` - **依赖注入** 采用Hilt实现自动化依赖管理: ```kotlin @Module @InstallIn(SingletonComponent::class) object NetworkModule { @Provides fun provideRetrofit(): Retrofit = Retrofit.Builder() .baseUrl("https://api.example.com/") .addConverterFactory(GsonConverterFactory.create()) .build() } ``` #### 2. **性能优化技术** - **启动加速** 优化冷启动时间公式: $T_{\text{total}} = T_{\text{init}} + T_{\text{load}} + T_{\text{render}}$ 通过`App Startup`库延迟初始化非关键组件: ```xml <provider android:name="androidx.startup.InitializationProvider" tools:node="remove" /> ``` - **内存优化 使用`Memory Profiler`检测泄漏,结合`LeakCanary`自动捕获: ```gradle dependencies { debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1' } ``` #### 3. **安全加固方案** - **防二次打包** 实现签名验证(参考站内引用[^1]): ```kotlin fun validateAppSignature(context: Context): Boolean { val packageName = context.packageName val packageInfo = context.packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES) return packageInfo.signatures[0].toByteArray().contentEquals(EXPECTED_SIGNATURE) } ``` - **代码混淆与加密** 启用R8混淆并配置规则: ```gradle buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } ``` #### 4. **响应式编程** - **Kotlin协程进阶** 使用`Flow`实现复杂数据流: ```kotlin fun fetchData(): Flow<Result> = channelFlow { send(Result.Loading) try { remoteDataSource.getData().collect { send(Result.Success(it)) } } catch (e: Exception) { send(Result.Error(e)) } } ``` #### 5. **跨平台技术** - **Jetpack Compose** 声明式UI开发示例: ```kotlin @Composable fun Greeting(name: String) { var clicked by remember { mutableStateOf(false) } Text( text = if (clicked) "Clicked!" else "Hello $name", modifier = Modifier.clickable { clicked = !clicked } ) } ``` #### 6. **自动化与测试** - **模块化测试策略** 分层测试金字塔: $$ \text{Unit Tests} > \text{Integration Tests} > \text{UI Tests} $$ 使用`MockK`进行单元测试: ```kotlin @Test fun `test user fetch`() = runTest { val mockRepo = mockk<UserRepository>() coEvery { mockRepo.getUser() } returns User("Admin") val viewModel = UserViewModel(mockRepo) viewModel.fetchUser() assert(viewModel.userState.value is Success) } ``` ### 学习路径建议 1. 掌握Kotlin协程与Flow 2. 实践Jetpack Compose项目 3. 学习性能优化工具(Profiler, Baseline Profiles) 4. 研究安全加固方案(如防篡改技术[^1]) 5. 构建模块化应用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值