文章目录
一、 Jetpack是什么
百度下都是差不多的说明,我这里结合自己的理解记录下,可能理解的也不是很全面正确。
Jetpack是一套工具库,包含4类组件、分别是架构、界面、行为、基础。(这里不结合代码个人感觉也不太好理解)。因为是一套工具库,可以单独使用,也可以配合使用。每个组件都给用户提供了一个标准,能够帮助开发者遵循最佳做法。(意思就是好用呗)。
这里从copy了一张图,大体了解下:
从图片可以看出,4大类,每种分类下面好多工具,这里学到哪个,通过简单的例子记录下,方便自己理解,如果能帮到其他人,是我的荣幸。
Android也是更新的非常快,有些类和方法已经过时,我这里的环境是AS环境如下,例子中使用的库的版本我都会写出来,方便以后学习使用。
二、架构之Data Binding
Data Biding 位于架构(Architecture)中,(ps:百度翻译是建筑,反正软件是一种工程学,一个意思吧),学的太抽象有时候也不太好理解,暂时都把这个理解成工具库,学习并简单使用,可能写的多了,思想的层次及代码水平会提高。
1. Data Binding的使用
使用DataBinding可以将View和Model中的数据绑定在一块,即可以单向绑定,也可以双向绑定。也不需要再写findViewById这类代码,真香。通过下面的例子简单学习下。
大家都知道使用三方库需要添加依赖,Data Binding作为工具,我们在AS中配置启用就可以使用了。
在当前模块build.gradle配置文件中android节点下添加:
android {
...
buildFeatures{
dataBinding = true
}
...
}
就是这么简单,我们就可以使用了。
要使用Data Binding 需要对Activity和xml中的代码简单修改下。
首先看xml中的布局代码(activity_main.xml):
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="hello DataBinding" />
</RelativeLayout>
</layout>
这里要着重注意下,布局文件要以layout标签作为根标签,里面就可以写我们的布局了。
接着再来看Activity中的代码,
public class MainActivity extends AppCompatActivity {
ActivityMainBinding mBinding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// mBinding = ActivityMainBinding.inflate(getLayoutInflater());
// setContentView(mBinding.getRoot());
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
}
}
这里???,没使用过的时候有点蒙,ActivityMainBinding 这哪来的了?这个其实是DataBinding帮我们生成的类,对应就是(activity_main.xml)文件,用鼠标点进去也是直接跳转的布局文件,仔细看这个布局文件和命名(activity_main)和生成类的名字(ActivityMainBinding),这里是对应关系,首字母大写+(_后面首字母大写)+Binding
这里需要注意下,以前是调用
setContentView
使用DataBinding是调用
DataBindingUtil.setContentView()
在DataBindingUtil.setContentView()里面调用了activity.setContentView
接着我们就可以使用布局中的控件了
public class MainActivity extends AppCompatActivity {
ActivityMainBinding mBinding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
mBinding.tv.setText("修改文本");
}
}
直接可以调用到布局中的TextView是不是很方便,这里面只有一个TextView,如果有大量的控件,调用就相当方便了,不用写大量的findViewById。
2.简单分析下原理
ActivityMainBinding 这个类没法直接通过鼠标点击进行,那打个包,反编译看下源码吧(费劲)
public abstract class ActivityMainBinding extends ViewDataBinding {
@Bindable
protected String mData;
public final TextView tv;
protected ActivityMainBinding(Object paramObject, View paramView, int paramInt, TextView paramTextView) {
super(paramObject, paramView, paramInt);
this.tv = paramTextView;
}
public static ActivityMainBinding bind(View paramView) {
return bind(paramView, DataBindingUtil.getDefaultComponent());
}
@Deprecated
public static ActivityMainBinding bind(View paramView, Object paramObject) {
return (ActivityMainBinding)bind(paramObject, paramView, 2131427356);
}
public static ActivityMainBinding inflate(LayoutInflater paramLayoutInflater) {
return inflate(paramLayoutInflater, DataBindingUtil.getDefaultComponent());
}
public static ActivityMainBinding inflate(LayoutInflater paramLayoutInflater, ViewGroup paramViewGroup, boolean paramBoolean) {
return inflate(paramLayoutInflater, paramViewGroup, paramBoolean, DataBindingUtil.getDefaultComponent());
}
@Deprecated
public static ActivityMainBinding inflate(LayoutInflater paramLayoutInflater, ViewGroup paramViewGroup, boolean paramBoolean, Object paramObject) {
return (ActivityMainBinding)ViewDataBinding.inflateInternal(paramLayoutInflater, 2131427356, paramViewGroup, paramBoolean, paramObject);
}
@Deprecated
public static ActivityMainBinding inflate(LayoutInflater paramLayoutInflater, Object paramObject) {
return (ActivityMainBinding)ViewDataBinding.inflateInternal(paramLayoutInflater, 2131427356, null, false, paramObject);
}
public String getData() {
return this.mData;
}
public abstract void setData(String paramString);
}
从上面的代码,可以看出ActivityMainBinding是个抽象类,继承自ViewDataBinding 。这个控件也是public的,所以可以直接调用mBinding.tv来调来控件中的方法。
接着再来看下DataBindingUtil.setContentView具体调用了哪些方法:
DataBindingUtil是可以通过鼠标点击进入查看源码的,这里也不具体分析细节了,流程都可以打断点查看调用栈,这里只是简单分析下:
通过鼠标点点点,找到这个方法,sMapper.getDataBinder,看下sMapper的实现类是DataBinderMapperImpl,点击进入
这应该是个装饰器吧,实际调用的是 DataBinderMapperImpl类的getDataBinder方法:
接着鼠标点点点,这里的代码是可以打断点的,不清楚的可以打个断点跟下流程
getDataBinder的能过layoutId找到ActivityMainBindingImpl类,从命名和调用分析上都能看出来,这是ActivityMainBinding的实现类,这里有个疑问,view.getTag()?这里面的tag是什么时候设置的了,从调用上没找到,其实应该是databinding帮我们在xml文件里面添加了tag,通过AS查看生成的包:
接着看下ActivityMainBinding的实现类ActivityMainBindingImpl中可以看到设置界面的方法,
这里就简单分析到这,通过鼠标点点点都可以找到这些调用的方法。
3. Data Binding绑定数据(单向绑定)
接着我们来绑定一个变量,来看如何使用DataBinding绑定数据
首页xml中需要增加声明一个变量
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="data"
type="String" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@{data}" />
</RelativeLayout>
</layout>
这里注意,我们声明的数据要放到 data标签中, variable 就是声明一个变量,name就是名字,type就是类型。在需要绑定View的地方使用
@{name},相当于控件中的text属性绑定到 data 变量上。
总结下:
使用DataBinding 构建的布局文件中,要以layout作为根标签,如果要绑定数据,数据放到 data 标签中,data标签与 布局根标签并列,大体意思如下
<layout>
<data>
// 声明数据
</data>
<view>
// 布局
</view>
</layout>
然后再来看Activity中的代码
public class MainActivity extends AppCompatActivity {
ActivityMainBinding mBinding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
mBinding.setData("Hello DataBinding");
}
}
这里通过mBinding.setData(“Hello DataBinding”);来给TextView设置文本了,这里是不是很有意思了,通过DataBinding,在xml中声明变量绑定到View上,在Activity设置变量,既可实现数据的绑定,注意,这里是一种单向绑定
mBinding.setData("Hello DataBinding");
mBinding.setData("修改变量");
通过以上调用 TextView中显示的文本是“修改变量”,通过修改 data 数据来改变 View 的显示,这是数据与View的单向绑定,如果View发生了变化,那 data 会改变吗?这里验证下:
public class MainActivity extends AppCompatActivity {
ActivityMainBinding mBinding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
mBinding.setData("Hello DataBinding");
mBinding.setData("修改变量");
new Handler().postDelayed(() -> {
mBinding.tv.setText("文本1");
Toast.makeText(this, mBinding.getData(), Toast.LENGTH_LONG).show();
}, 2000);
}
}
在之前的代码基础上,增加了一个延时操作,设置TextView文本,Toast显示之前绑定的变量,这里不贴图了,实际运行效果是,TextView显示的内容变为了 文本1,Toast显示的内容还是之前的 修改变量。这里也证明了,上述使用的是单向绑定,那有没有双向绑定了?有的,DataBinding真是太强大了 yyds。
4. Data Binding绑定数据(双向绑定)
还是在原来的基础上,布局如下:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="data"
type="String" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@={data}" />
</RelativeLayout>
</layout>
仔细看,会发现于之前单向绑定是 @{data} ,现在是 @={data}。what?这么简单吗?yes,就是这么简单就实现了~数据和View的双向绑定
再来看Activity中的代码
public class MainActivity extends AppCompatActivity {
ActivityMainBinding mBinding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(mBinding.getRoot());
mBinding.setData("Hello DataBinding");
mBinding.setData("修改变量");
new Handler().postDelayed(() -> {
mBinding.tv.setText("文本1");
Toast.makeText(this, mBinding.getData(), Toast.LENGTH_LONG).show();
}, 2000);
}
}
还是熟悉的代码,熟悉的味道,这次运行会发现,在延时2s后,TextView的内容变成了 文本1 ,Toast显示的内容也是 文本1,真是太神奇了。
通过DataBinding来实现数据与View的绑定,大大提升了开发效率,首先对于xml中的大量控件不需要findViewById了,可以使用data来绑定View中的属性,这样加载的时候可以显示默认效果,也可以双向绑定,在用户操作后,对应的 data 自动同步,我们就可以直接获取对应的数据,做相应的操作了。更关注于业务本身。
5. Data Binding使用总结
1.需要在build.gradle中配置使用 databinding 来构建项目
2.xml布局文件需要使用layout 标签作为根标签,data 标签来声明数据。需要注意xml文件名对应生成Binding类名对应
3.Activity中的代码需要做修改,来加载对应的Binding类
4.单向绑定使用 @{xxx} ,双向绑定使用 @={xxx}
后记:
这里也是自己理解学习记录,有些地方理解的不对的地方希望大家在评论中指出,后续会接着写JetPack相关的工具使用。谢谢~