Jetpack学习之DataBinding(一)

一、 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相关的工具使用。谢谢~

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值