android:layout_width=“match_parent”
android:layout_height=“48dp”
android:layout_margin=“24dp”
android:insetTop=“0dp”
android:insetBottom=“0dp”
android:text=“登 录”
app:cornerRadius=“12dp” />
③ 实现登录
下面回到MainActivity中,增加代码如下图所示:
乍一看好像没啥不同的,无非就是给mainViewModel中的两个变量赋了值。不过这里有一个数据持久化的内容在里面,怎么证明呢?看一下下面这个GIF图
这个图可能有一些黑屏的地方,因为我在给自己的手机做横竖屏切换的时候,手机录屏好像有一点问题,不过没事。因为这个结果是对的,那就是数据持久化,因为我们知道手机在切换屏幕的时候Activity是会重新创建的,因此如果我们的数据是放在Activity中,那么切换屏幕之后就会重置,输入框也不会有值,但是通过ViewModel去保存输入框的值就不同了,虽然你的Activity在切换屏幕的时候销毁并且重新创建了,但是我的MainModel依然稳定,所以我才能在横屏的时候也登陆,这样不会造成数据丢失。
LiveData是用来做什么的?数据变化感知,也就是说如果我一个页面中对一个TextView进行多次赋值的话,可以通过LiveData来操作,只需要在值改变的时候进行设置就好了,可以简化页面上的代码。下面举一个实际的例子来说明。依然是之前那个登录页面,不过需要修改一下MainViewModel中的变量,如下:
① 可修改数据
public MutableLiveData account = new MutableLiveData<>();
public MutableLiveData pwd = new MutableLiveData<>();
请注意这里使用的是MutableLiveData,表示值的内容开变动,而LiveData是不可变的。<>中的是泛型,你可以直接将一个对象放进去,当对象的内容有改动时,通知改变就可以了,现在这么写是为了方便理解。下面进入MainActivity中,首先我们改变一下布局activity_main.xml在按钮的下面再加如下代码
<TextView
android:id=“@+id/tv_account”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”/>
<TextView
android:id=“@+id/tv_pwd”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”/>
② 数据观察
然后回到MainActivity中,修改代码如下图所示:
上面的图中从上往下有四处标注,我们从下面的两处标注来看,首先在给MainViewModel中的account赋值时,采用了MutableLiveData的setValue()的方式,还有一种方式是postValue(),这里要注意一点setValue()只能在主线程中调用,postValue()可以在任何线程中调用。pwd也是一样的,然后在最后一处标注的地方,对MainViewModel中的account和pwd进行数据观察,当这两个值有改变时通知页面最新的值,这里用了lambda表达式进行了一次简化,实际的代码是这样的。
下面我们运行一下:
Android的DataBinding在已经内置了,因此只需要在app模块的build.gradle中开启就可以使用了。DataBinding,顾名思义就是数据绑定,可以看到现在的三个组件都与数据有关系,ViewModel数据持有,LiveData数据观察、DataBinding数据绑定。
① 单向绑定
而DataBinding的绑定有两种方式:单向数据绑定和双向数据绑定。举个例子:比如我手机上收到一个通知,我需要显示通知的文字内容在页面上,这就是单向绑定,而我页面上的文字内容改变也重新发一个通知出去,这就是双向绑定。可以理解为A和B进行交互。A发消息,B要做出反应。B发消息,A也要相应改变。最常用的就是当我Model中的数据改变时,改变页面上的值。这个是单向绑定。下面我们可以新建一个用户User对象,代码如下:
public class User extends BaseObservable {
private String account;
private String pwd;
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
notifyChange();//通知改变 所有参数改变
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public User(String account, String pwd) {
this.account = account;
this.pwd = pwd;
}
}
这里我继承了BaseObservable,注意它在androidx.databinding包下。然后我们的数据是需要显示在页面上的,而之前是通过Activity获取xml中的控件,然后显示数据在控件上,而现在有了DataBinding,可以直接和xml的中数据进行绑定,这看起来和JS比较像。下面我们对activity_main.xml进行改变。改变后代码如下:
<?xml version="1.0" encoding="utf-8"?><layout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:app=“http://schemas.android.com/apk/res-auto”
xmlns:tools=“http://schemas.android.com/tools”>
<variable
name=“user”
type=“com.llw.mvvm.User” />
<LinearLayout
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:gravity=“center”
android:orientation=“vertical”
android:padding=“32dp”
tools:context=“.MainActivity”>
<com.google.android.material.textfield.TextInputLayout
android:layout_width=“match_parent”
android:layout_height=“wrap_content”>
<com.google.android.material.textfield.TextInputEditText
android:id=“@+id/et_account”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:background=“@color/white”
android:hint=“账号” />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:layout_marginTop=“12dp”>
<com.google.android.material.textfield.TextInputEditText
android:id=“@+id/et_pwd”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:background=“@color/white”
android:hint=“密码”
android:inputType=“textPassword” />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id=“@+id/btn_login”
android:layout_width=“match_parent”
android:layout_height=“48dp”
android:layout_margin=“24dp”
android:insetTop=“0dp”
android:insetBottom=“0dp”
android:text=“登 录”
app:cornerRadius=“12dp” />
<TextView
android:id=“@+id/tv_account”
android:text=“@{user.account}”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”/>
<TextView
android:id=“@+id/tv_pwd”
android:text=“@{user.pwd}”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”/>
这里我在最外层加了一个layout标签,然后将原来的布局放在layout里面,再增加一个数据源,也就是user对象,然后再底部的两个tv_account和tv_pwd两个TextView中的text属性中绑定了user对象中的属性值。当然这样还没有完成,最后一步是在MainActivity中去进行绑定的。
进入MainActivity。在onCreate方法中,先将其他的代码注释掉。
然后修改待明日如下图所示
这里要注意一点,DataBindingUtil.setContentView返回的是一个ViewDataBinding对象,这个对象的生成取决于你的Activity,例如MainActivity,就会生成ActivityMainBinding。然后再通过生成的ActivityMainBinding去设置要显示在xml中控件的值。因此你会看到我完全没有去findViewById,然后控件再去设置这个setText。还有一点就是当你使用了DataBinding之后就不需要去手动findViewById了,通过编译时技术会生成驼峰命名的对象,如上图的btnLogin、etAccount、etPwd。上图的代码就是通过更改数据然后通知到xml做更改,初始化的修改时admin、123456。然后再通过输入框去修改。我将会输入study、666,然后点击登录按钮,也会将输入框的数据显示在TextView上,这样是否会省去很多不必要的繁琐工作呢?下面运行一下:
② 双向绑定
双向绑定是建立在单向绑定的基础上,实际的开发中用到双向绑定的地方并没有单向绑定多,双向绑定举一个例子,在输入框输入数据时候直接将数据源中的数据进行改变,这里会用到ViewModel和LiveData。下面进行双向绑定的使用,修改一下MainViewModel,代码如下:
public class MainViewModel extends ViewModel {
public MutableLiveData user;
public MutableLiveData getUser(){
if(user == null){
user = new MutableLiveData<>();
}
return user;
}
}
下面修改User类,这里面做了一些改变
public class User extends BaseObservable {
public String account;
public String pwd;
@Bindable
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
notifyPropertyChanged(BR.account);//只通知改变的参数
}
@Bindable
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
notifyPropertyChanged(BR.pwd);//只通知改变的参数
}
public User(String account, String pwd) {
this.account = account;
this.pwd = pwd;
}
}
不同于notifyChange()改变某一个参数,某一个对象都会通知,现在notifyPropertyChanged()就具有针对性,只通知对应属性改变。之前在activity_main.xml中的data标签中是使用的User,现在我们改成ViewModel,顺便把布局调整一下,代码如下:
<?xml version="1.0" encoding="utf-8"?><layout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:app=“http://schemas.android.com/apk/res-auto”
xmlns:tools=“http://schemas.android.com/tools”>
<variable
name=“viewModel”
type=“com.llw.mvvm.viewmodels.MainViewModel” />
<LinearLayout
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:gravity=“center”
android:orientation=“vertical”
android:padding=“32dp”
tools:context=“.MainActivity”>
<TextView
android:id=“@+id/tv_account”
android:text=“@{viewModel.user.account}”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”/>
<TextView
android:layout_marginBottom=“24dp”
android:id=“@+id/tv_pwd”
android:text=“@{viewModel.user.pwd}”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”/>
<com.google.android.material.textfield.TextInputLayout
android:layout_width=“match_parent”
android:layout_height=“wrap_content”>
<com.google.android.material.textfield.TextInputEditText
android:id=“@+id/et_account”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:background=“@color/white”
android:text=“@={viewModel.user.account}”
android:hint=“账号” />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:layout_marginTop=“12dp”>
<com.google.android.material.textfield.TextInputEditText
android:id=“@+id/et_pwd”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:background=“@color/white”
android:text=“@={viewModel.user.pwd}”
android:hint=“密码”
android:inputType=“textPassword” />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id=“@+id/btn_login”
android:layout_width=“match_parent”
android:layout_height=“48dp”
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
分享读者
作者2013年java转到Android开发,在小厂待过,也去过华为,OPPO等大厂待过,18年四月份进了阿里一直到现在。
被人面试过,也面试过很多人。深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长,而且极易碰到天花板技术停滞不前!
我们整理了一份阿里P7级别的Android架构师全套学习资料,特别适合有3-5年以上经验的小伙伴深入学习提升。
主要包括阿里,以及字节跳动,腾讯,华为,小米,等一线互联网公司主流架构技术。如果你有需要,尽管拿走好了。
35岁中年危机大多是因为被短期的利益牵着走,过早压榨掉了价值,如果能一开始就树立一个正确的长远的职业规划。35岁后的你只会比周围的人更值钱。
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
会持续更新**
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-UBU5RlqT-1712767750676)]
分享读者
作者2013年java转到Android开发,在小厂待过,也去过华为,OPPO等大厂待过,18年四月份进了阿里一直到现在。
被人面试过,也面试过很多人。深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长,而且极易碰到天花板技术停滞不前!
我们整理了一份阿里P7级别的Android架构师全套学习资料,特别适合有3-5年以上经验的小伙伴深入学习提升。
主要包括阿里,以及字节跳动,腾讯,华为,小米,等一线互联网公司主流架构技术。如果你有需要,尽管拿走好了。
[外链图片转存中…(img-YIUwBEhJ-1712767750676)]
35岁中年危机大多是因为被短期的利益牵着走,过早压榨掉了价值,如果能一开始就树立一个正确的长远的职业规划。35岁后的你只会比周围的人更值钱。
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-BKy5qEeN-1712767750676)]