Android开发之DataBinding+LiveData+ViewModule
众所周知,Android海外主流开发已经开始使用Google最新提供的JetPack Compose进行开发。
Compose使用MVI框架,代表了应用开发从命令式编程向响应式编程的转变。(翻译原因,也叫做声明式编程)
转过头国内的开发人员发现,DataBinding+LiveData+ViewModule 这种搭配,居然还没成为主流。
海外已经开始用Kotlin协程 +JetPack Compose 进行开发了。
说句题外话,国内因为特殊原因,你懂得。不管是从Android 最新SDK版本的普及,还是开发方式都落后于国际项目。
这波趋势是无法避免的,就像当年Google推进AndroidStudio代替Eclipse一样。Kotlin在Androoid开发方向上一定会逐步占据主流。
特别是应用层开发,作为Android,IOS,H5,Flutter,VUE都开发过得我来说,由衷的体会到,应用层开发会越来越简洁。不管是响应式编程这个概念的崛起,还是逐步递增迭代的语法优化:空安全检查,Lambda表达式。各种好用的UI框架组件等等。
如果想在应用层开发上,走得远只有两条路了,唯有广度和深度两个方向而已。
要不然你就垂直开发能力很强,精通Android底层一直到应用层。要不然你就需要掌握多种开发语言,就是所谓的跨平台能力。
废话不多说了,今天的主题主要是和讲DataBinding+LiveData+ViewModule。 其实这玩意入门很简单。我先普及一下概念。
我会从是什么,干嘛用,怎么用。三个维度来讲。
DataBinding:
是什么?:
将布局中的界面组件 与 应用中的数据源 进行绑定
干嘛用?:
我们使用它之后,就不需要再使用某一个控件时去findviewbyid了。
findViewById<TextView>(R.id.sample_text).apply {
text = viewModel.userName
}
换句话说,我们可以更简单的使用视图树上的控件节点。不用关心它的声明周期,只要能获取到,说明就是存在的。
只要启动了Databinding,AndroidStudio会根据xml元素自动在生成对应的布局类。是个全局对象,直接可以通过点点点的方法获取控件。
比如你的布局名字是activity_login.xml
那对应的全局对象就是ActivityLoginBinding。
这种写法可以很好的避免,空异常崩溃。之前我们操作数据刷新,如果控件为空,就APP就崩了。
怎么用?:
build.gradle 文件中将 dataBinding 构建选项设置为 true,如下所示:
android {
...
buildFeatures {
dataBinding true
}
}
布局xml文件需要注意对Activity的对应绑定关系:
private ActivityLoginBinding binding;
binding = ActivityLoginBinding.inflate(getLayoutInflater());
final EditText usernameEditText = binding.username;
LiveData + ViewModule 这一对儿是相辅相成的关系。他们是Android项目MVVM框架,VM实现的核心。
多说一句,这里的ViewModule 和 框架的ViewModule是两个东西。后者框架是概念,是整个数据绑定View,实现数据去驱动UI的核心层。 前者是封装的操作对象,你可以理解为工具类。
LiveData
是什么?
一种可观察的数据存储器类。 具有生命周期感知能力,可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
它的核心实现就是个观察者模式。通过对数据进行注册观察,来更新数据变化给UI。而最妙的是,只有在前台这种活跃的生命周期下,它才会更新回调。
干嘛用?:
确保界面符合数据状态,不会发生内存泄漏,不会因 Activity 停止而导致崩溃,不再需要手动处理生命周期,数据始终保持最新状态。
怎么用?:
这玩意和viewModule是配对使用的。一个viewmodule相当于工具类。里面可以有多个livedata。
private LoginViewModel loginViewModel;
loginViewModel.getLoginFormState().observe(this, new Observer<LoginFormState>() {
@Override
public void onChanged(@Nullable LoginFormState loginFormState) {
// do some sth
}
});
通过observe对数据进行观察者注册监听。在onChangged接收数据变化回调。真的方便的一批。
而loginViewModule是继承与viewMdoule,里面就是对数据进行livedata封装的操作,我们看下:
public class LoginViewModel extends ViewModel {
private MutableLiveData<LoginResult> loginResult = new MutableLiveData<>();
LiveData<LoginResult> getLoginResult() {
return loginResult;
}
public void login(String username, String password) {
// can be launched in a separate asynchronous job
Result<LoggedInUser> result = loginRepository.login(username, password);
if (result instanceof Result.Success) {
LoggedInUser data = ((Result.Success<LoggedInUser>) result).getData();
loginResult.setValue(new LoginResult(new LoggedInUserView(data.getDisplayName())));
} else {
loginResult.setValue(new LoginResult(R.string.login_failed));
}
}
我们看到MutableLiveData这个东西会一脸懵逼,但其实这是liveData的一个抽象子类。实际上就是livedata,从这个getLoginResult函数的回调对象我们就可以确认。
并且MutableLiveData实现在下面:
public class MutableLiveData<T> extends LiveData<T> {
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
}
我们可以看到主要是对包括的数据,暴露出了post和set两个函数。
setValue()只能在主线程中调用,postValue()可以在任何线程中调用。