findViewById替代方案:Android Jetpack MVVM之BindingAdapter

2023-05-16

本文的目标是阐述BindingAdapter使用方法并以点击事件为例

在介绍它之前,我们先讲一下,布局文件中的系统属性android:onClick="" ,不知道你有没有用过,其中双引号中间就是你要触发的事件名称。不需要用findViewById获取对应控件,然后再监听click事件,若是你用过请略过,若是没有过,我们看看怎么用的。

举个例子:
在布局文件中设置android:onClick=“clickEvent”

<ImageView    
        android:layout_width="wrap_content"    
        android:layout_height="wrap_content"    
        android:onClick="clickEvent"   
        android:src="@drawable/tes" />

在activity中新建一个clickEvent函数:

public void clickEvent(View v) {   
    Toast.makeText(this, "test", Toast.LENGTH_LONG).show();
}

这样就直接可以监听ImageView的单击事件,这样是不是很方便,为啥要介绍这个呢,是因为本文BindingAdapter也要采用同样的方式来实现,只是我们不采用系统的定义的属性,而是自己定义属性。

首先要讲一下attrs.xml,它是res/values目录下的一个文件,为什么讲它?因为它跟bindingadapter紧密相连。

  • 自定义属性
    自定义性有两个部分组成,第一,属性名,也就是名字,第二,属性值,也就是属性格式format。看下面的一段代码:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="backColor" format="color">
        <enum name="redColor" value="1" />
    <declare-styleable name="MyView">
        <attr name="backColor"/>
    </declare-styleable>
</resources>

以attr开头的代表着具体某个属性。

以declare-styleable代表的某个组。例如我想为一个view自定义一个属性,假设这个view为MyView,则MyView下面定义所有属性都属于MyView组,凡是继承它的都可以使用。当然也可以为系统控件加上自定义属性。

系统属性和自定义属性是有区别的,属性名前面有“android:”都是系统属性。自定属性名没有没有什么好说的,尽量不要和系统定义的属性名雷同。

若是和系统定义的属性一样,不设置format的话,就沿用系统的。若是设置的话,就是对系统属性的重定义,但是有些系统属性格式是无法修改的。

简单介绍一下属性的format:

reference 引用
color 颜色
boolean 布尔
integer 整型
dimension
float 浮点型
string 字符型
fraction 百分比
enum 枚举型
flag

自定义属性搞定了,其实没什么难度,那么接下来,我们要看看如何自定义属性和BindingAdapter建立连接的呢。其实也很简单,还是以一个例子来说明

  • 首先,自定义属性,我们给系统的控制View自定义onClickCommand属性,只要属于View这个组的都可以使用这个属性。
<resources>
       <declare-styleable name="View">
           <attr name="onClickCommand" format="reference" />    
       </declare-styleable>
 </resources>

这个属性name,就是BindingAdapter的关键。

  • 其次,BindingAdapter

它的一般格式为:

@BindingAdapter(value={“属性名1”,“属性名2”})
public static void 函数名(参数){
//函数内容
}

具体的实例如下:新建一个文件为ViewAdapter.java,并类中添加如下代码

@BindingAdapter(value = {"onClickCommand"}, requireAll = false)
public static void click(View view, final ClickCallBack bindingCommand) {    
    view.setOnClickListener(new View.OnClickListener() {        
        @Override        
        public void onClick(View view) {           
        if (bindingCommand != null) {                
           bindingCommand.clickEvent();               
           Toast.makeText(view.getContext(), "it works", Toast.LENGTH_LONG).show();           
        } else {                
            Toast.makeText(view.getContext(), "binding command is null", Toast.LENGTH_LONG).show();           
        }        
    }    
 });
}

BindingAdapter中value要和attrs.xml中自定义属性保持一致,否则绑定不成功。

绑定的函数一定要是static的,函数名没有具体的要求,函数里面的第一个参数为要绑定对象,我们绑定的为View,那就是View;

后面的参数就是各个属性,在布局文件中一定要按顺序进行,否则可能会报错。

还需要在布局文件中应用这个属性

<ImageView
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content"
        android:src="@drawable/tes"   
        binding:onClickCommand="@{viewmodel.mBindingCommand}" 
/>

到目前为止,代码层面是没有问题,但是还不能用,因为还要binding。

ActivityMainBinding binding = DataBindingUtil.setContentView(this, getLayoutResId()); 

其中ActivityMainBinding是系统自动生成的,这一步实现布局文件和属性之间进行绑定,也就是可以实现单击事件了。

最后,我们不仅要是实现事件绑定还能在ViewModel中回调,因为需要对事件进行业务的处理

在ViewModel中,需要具体实现BindingAdapter的回到,如下:

public ClickCallBack mBindingCommand = new ClickCallBack() {    
    @Override    
    public void clickEvent() {        
    Log.e("tag", "click");    
    }
};

只需要在布局文件中绑定这个回调即可生效。

但是你发现回调对象为空,因为还需要设置

binding.setVariable(BR.viewmodel, mViewModel);

这样才是完整的BindingAdapter过程。

值得注意的是binding.setVariable(BR.viewmodel, mViewModel);必须在创建ViewModel之后,否则你绑定回调参数为空,因为ViewModel没有创建为空,可以看自动生成的代码,自动生成的代码也可调试。

若是你想统一对ImageView都用Glide进行加载图片,你就可以通过这个中方式实现

@BindingAdapter({"imageUrl"})
    public static void loadImage(ImageView view, String u) {
        RequestOptions options = new RequestOptions()
                .centerCrop()
                .placeholder(R.mipmap.ic_launcher_round)
                .error(R.mipmap.ic_launcher)
                .priority(Priority.HIGH)
                .diskCacheStrategy(DiskCacheStrategy.NONE);
        Glide.with(view.getContext()).applyDefaultRequestOptions(options).load(u).transition(new DrawableTransitionOptions().crossFade(1000)).into(view);
    }

代码量会很少,效率会很高。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

findViewById替代方案:Android Jetpack MVVM之BindingAdapter 的相关文章

随机推荐

  • JS五子棋(AI)

    JS五子棋 AI xff09 跟随算法 xff1a 白棋始终跟随当前黑棋周围 span class token doctype span class token punctuation lt span span class token do
  • Discuz7.2漏洞

    发布日期 xff1a 2010 01 06 更新日期 xff1a 2010 01 07 受影响系统 xff1a Discuz Discuz 7 1 Discuz Discuz 7 2 描述 xff1a Discuz 是一款华人地区非常流行的
  • vfp常见问题和代码

    1 VFP为何在编译时提示找不到菜单生成程序 xff1a 设置 GENMENU 系统内存变量到适当的路径和文件 例如 假定 FoxPro 安装在 C 盘上的 VFP 中 在命令窗口打入以下命令来恢复系统变量的值 GENMENU 61 34
  • VFP中Form的重要概念

    本文所指的 34 表单窗口属性 34 是指那些不但影响表单本身的特征 xff0c 而且对表单之外 项目之中的其它 34 元件 34 有影响的表单属性 xff0c 它们是 xff1a 属性 意义 可选值 黑体为默认值 DeskTop 指定表单
  • MacOS M1芯片安装PyQt5的方法

    MacOS M1芯片安装 PyQt5 的方法 关于PyQt5 PyQt5 是GUI 小部件工具包 xff0c 是 Qt 的 Python 接口 xff0c 是图形界面开发库 xff0c 用于程序的用户交互界面 按照官网 PyQt5 pypi
  • iOS富文本编辑(在label里显示文字和图片)

    在开始写之前先看一下效果图 在此效果图中有富文本中指定的位置添加图片 xff0c 还有最后位置添加的图片信息 代码如下 调用方法 给label赋值 NSString Str 61 64 34 中国人民解放军万岁 xff0c 中华人民共和国万
  • ubuntu下安装VNC远程桌面的详细步骤

    作者 xff1a 转自 xff1a http www 5loveb com 4 515 html Virtual Network Computing VNC 是进行远程桌面控制的一个软件 客户端的键盘输入和鼠标操作通过网络传输到远程服务器
  • 服务器esxi安装

    一 部署raid0或raid1 xff08 Raid0的配置过程与Raid1大致相同 xff0c 唯一不同是在选择Raid级别这一步选择Raid0即可 xff09 xff08 一 xff09 在RAID卡适配器自检页面按组合键Ctrl 43
  • MFC编辑框数据读写

    简介 xff1a 有几种常用的获取编辑框内容和写入的方法 xff0c 初学者往往容易迷惑 1 第一种 通过GetDlgItem和GetWindosText char szEdit 10 61 0 int nEdit 61 0 GetDlgI
  • Peer cert cannot be verified or peer cert invalid 解决方法

    yum安装软件时报Peer cert cannot be verified or peer cert invalid xff0c 如下图所示 xff1a 解决办法 xff1a 在 etc yum conf文件后追加sslverify 61
  • 在anaconda中为jupyter安装扩展插件

    安装过程 xff1a 1 在开始菜单中打开Anaconda Prompt 2 执行如下安装命令 xff1a conda install c conda forge jupyter contrib nbextensions conda ins
  • 降低代码耦合度的方法 -依赖注入

    降低代码耦合度的方法 依赖注入 什么是依赖注入为什么要使用依赖注入Laravel中的依赖注入 什么是依赖注入 什么是依赖注入 xff0c 就要先了解什么是依赖 在面向对象语言中 xff0c A类需要引用B类中Y方法的 xff0c 则称A类和
  • 接入腾讯应用宝(YSDK)注意事项

    接入腾讯ysdk只想说 xff0c 其文档写的真是差 xff01 很多东西摸不着头尾 xff0c 在这期间走了很多坑 第一个 xff1a 拉起手Q时 xff0c 出现100044画面错误 造成这个的因素有很多 xff1a 1 xff0c 未
  • ubuntu20.04 使用root用户自动登录系统

    Ubuntu20 04安装完成之后 xff0c 默认是没有root账户登录权限的 xff0c 这样在操作系统时有诸多不便 xff0c 比如新建一个文件都提示权限不够 xff01 不过可以通过创建的普通用户获取管理员权限 xff0c 然后修改
  • Ubuntu——虚拟显示器的配置、卸载、修改分辨率

    参考博客 xff1a 安装虚拟显示器 xff1a VNC远程登录无外接显示器的Ubuntu Desktop卸载虚拟显示器 远程服务器虚拟显示器 xff08 Ubuntu 20 04 LTS xff09 修改分辨率 xff1a Ubuntu
  • 修改ubuntu的默认路由

    1 sudo route del default gw 192 168 6 1 删除默认路由 2 sudo route add default gw 192 168 6 1 添加默认路由 route 命令参考https www cnblog
  • 安装opencv3.2时出现 ICV: Failed to download ICV package: ippicv_linux_20151201.tgz.

    到链接 https pan baidu com s 1tUn4so6BZc8MdVz0FbtWLA 提取码 sktn xff0c 下载ippicv linux 20151201 tgz 并替换 opencv 3 2 0 3rdparty i
  • nuscenes数据读取和解析

    1 nuScenes数据集标注格式的说明 https blog csdn net qq 29679623 article details 103698313 utm medium 61 distribute pc relevant none
  • ubuntu16.04使用systemback给工控机还原系统

    1 由于使用 systemback备份系统的移动硬盘装有nvidia 460的驱动 xff0c 导致从移动硬盘启动后进入systemback备份的Ubuntu系统会出现循环登录的情况 xff0c 因此需要先卸载 systemback备份的U
  • findViewById替代方案:Android Jetpack MVVM之BindingAdapter

    本文的目标是阐述BindingAdapter使用方法并以点击事件为例 在介绍它之前 xff0c 我们先讲一下 xff0c 布局文件中的系统属性android onClick 61 34 34 xff0c 不知道你有没有用过 xff0c 其中