# Databinding引起的 java方法大于 65535 的问题

## 前言

项目中开发使用的是 MVVM 开发模式,并且选择了 Databinding 作为 ViewModel 和 View之间通信的桥梁,再加上一定的封装,使用起来是挺方便的,但是也会遇到一些坑,比如我遇到的这个:

**Databinding 生成的 Java 文件中方法大于 65535 问题。**

如下图所示:

![](https://markdown-1258186581.cos.ap-shanghai.myqcloud.com/20200305150649.png)

## 缘由

这个问题是怎么来的呢?

其实触发条件挺小的,只有在特定的情况下才会遇到,要满足下面的条件:

1. 使用 Databinding

2. 项目要是中大型的项目(使用 Databinding 的xml文件多)

3. gradle 插件的版本要小于 3.2.0

## 模拟发生

新建项目,然后新建一个 Module:lib2,项目结构如图所示

![](https://markdown-1258186581.cos.ap-shanghai.myqcloud.com/20200305151101.png)

然后分别在 app 和 lib2 的 build.gradle 中启用 Databinding

```shell

dataBinding{

enabled = true

}

```

设置 gradle 插件版本为 3.1.4. gradle 版本为:4.4

```shell

classpath 'com.android.tools.build:gradle:3.1.4'

distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

```

然后创建一个 layout 文件:tag_activity_lib_main.xml

```xml

xmlns:tools="http://schemas.android.com/tools"

tools:ignore="MissingDefaultResource">

android:id="@+id/ll"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

android:id="@+id/tv"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="test" />

```

然后利用脚本把这个 xml 文件拷贝2000份,并分别改名字:

脚本:

```shell

#!/bin/bash

for b in {1..2000}

do

cp tag_activity_lib_main.xml ./tag_activity_lib_main$b.xml

done

```

然后把生成的2000份 xml 文件拷贝到项目的 layout 目录下(app 和 lib2 目录各1000各)。

这个时候应该就会见到这个错误了:

![](https://markdown-1258186581.cos.ap-shanghai.myqcloud.com/20200305150649.png)

我们看下这个报错的 DatabinderMapperImpl :

![](https://markdown-1258186581.cos.ap-shanghai.myqcloud.com/20200305151909.png)

> ps:你的可能和我的不一样,xml 文件个数可能不同。

可以看到总共就那几个方法,却有2万多行代码,其中第一个 getDataBinder 方法很长,大概有15368 行,根据错误提示,可以初步断定就是就是这里的方法太大了,超过了 65535 的限制。

![](https://markdown-1258186581.cos.ap-shanghai.myqcloud.com/20200305163944.png)

可以看到这个 getDataBinder 的作用就是根据传进来的view 的 tag 和 layoutId来返回 和 layoutId 对应的 ViewDataBinding 对象。

即:在 gradle 3.1.4 版本中,会把所有 module 的带有 ...标签的 xml 文件都对应生成一个 ViewDataBinding对象,然后在 DataBinderMapperImpl 中的 getDataBinder 中提供对应的映射关系。

并且会把这个 DataBinderMapperImpl 类放在 app-build-generated-source-apt-android.databinding目录下面。

可以看到:这个 DataBinderMapperImpl 类是在 apt 文件夹下面,也就是这个类是在编译器生成的,这就涉及到了 Android 中的APT 技术,当然这里的编译时生成代码的过程是 google 已经写好的,代码地址在:

[databinding仓库](https://android.googlesource.com/platform/frameworks/data-binding/+/refs/tags/gradle_3.1.2/compiler/src/main/java/android/databinding/annotationprocessor/ProcessDataBinding.java) ,里面是具体的 APT 实现,有兴趣的可以去看看,其实是 google 在 Databinding 库中留下的坑,属于版本问题,好在后面的版本解决了这个问题。

## 解决

其实在 gradle 3.1.4 的下个版本 3.2.0中,google 已经解决这个问题。所以我们只用把 gradle 的版本升级到 3.2.0 以上就能避免这个问题的发生。

当然还有一个办法就是,后面你不再使用 Databinding 来开发,来避免这个问题,但是对于习惯使用 Databinding 的团队来说,这是很难受的,所以还是尽早升级下版本吧。

下面把 gradle 插件版本升级 3.2.0,并且同时要把 gradle 版本升级到 4.6.

执行编译:

![](https://markdown-1258186581.cos.ap-shanghai.myqcloud.com/20200305165129.png)

可见这里已经执行成功了。我们再来看下刚才 app - build 下面出错的 DataBinderMapperImpl 文件:

![](https://markdown-1258186581.cos.ap-shanghai.myqcloud.com/20200305165258.png)

看下 com.example.databindinganalysis 下面的 DataBinderMapperImpl:

![](https://markdown-1258186581.cos.ap-shanghai.myqcloud.com/20200305165411.png)

可以看到,在新版本的 DataBinderMapperImpl 的 getDataBinder 方法中,google 已经把获取 ViewDataBinding 的操作进行了拆分,使用 internalGetViewDataBindingXX 对所有的 layout 文件进行分组,每个组建立了 50 个映射关系,比如 internalGetViewDataBinding0 的代码如下:

![](https://markdown-1258186581.cos.ap-shanghai.myqcloud.com/20200305165557.png)

装对 getDataBinder 的拆分很好的避免了上面遇到问题的发生。

此外,在gradle 3.1.4 版本中,app module 和 lib2 module 的 DataBinderMapperImpl 文件都是在 app module 下面的 build 文件夹下面生成的,但是在 gradle 3.2.0 版本中,会对每个 module 都生成一个 DataBinderMapperImpl 文件,这样产生 上面代码过长的问题的概率又小了许多,事实上,一个正常的项目不会再发生上面的编译错误了。

最后再贴一下 Databinding 仓库的地址:

https://android.googlesource.com/platform/frameworks/data-binding/

65535 java_Databinding引起的 java方法大于 65535 的问题相关推荐

  1. ECMAScript 6(5)字符串与Unicode编码大于65535的字符

    字符串的扩展 前注:不关心细节的人,可以看[一句话总结]部分: 字符串的Unicode表示法 解释: 1. 首先,任意一个字符(比如数字.英文字符.汉字.符号等)都可以用Unicode的表示方法来表示 ...

  2. 一个Java方法能有多少个参数类型?这个好奇coder做了个实验

    在 JVM 中,一个 Java 方法,最多能定义多少参数呢?这是一个很无聊的问题,即使能定义一万个,十万个,谁又会真的去这么做呢.但是作为一个 coder,最重要的不就是好奇心吗,没有好奇心,和一条咸 ...

  3. 420一个像素多少个字节_一个Java方法能有多少个参数类型?这个好奇coder做了个实验...

    在 JVM 中,一个 Java 方法,最多能定义多少参数呢?这是一个很无聊的问题,即使能定义一万个,十万个,谁又会真的去这么做呢.但是作为一个 coder,最重要的不就是好奇心吗,没有好奇心,和一条咸 ...

  4. java方法参数类型不确定_一个Java方法能有多少个参数类型?这个好奇coder做了个实验...

    选自 justinblank 机器之心编译 参与:李志伟.张倩 在 JVM 中,一个 Java 方法,最多能定义多少参数呢?这是一个很无聊的问题,即使能定义一万个,十万个,谁又会真的去这么做呢.但是作 ...

  5. java定义一个空数组_一个 Java 方法,最多能定义多少参数?

    点击上方"JAVA",星标公众号重磅干货,第一时间送达 文链接:http://justinblank.com/experiments/howmanytypeparametersca ...

  6. java方法区内存泄露_深入理解java虚拟机-第二章:java内存区域与内存泄露异常...

    2.1概述: java将内存的管理(主要是回收工作),交由jvm管理,确实很省事,但是一点jvm因内存出现问题,排查起来将会很困难,为了能够成为独当一面的大牛呢,自然要了解vm是怎么去使用内存的. 2 ...

  7. java 方法执行结束局部变量释放_Java方法执行的内存模型

    Java虚拟机栈:Java方法执行的内存模型 Java虚拟机栈:Java方法执行的内存模型Java方法执行的内存模型当前线程:当前栈帧局部变量表操作数栈动态链接返回地址等信息...栈帧3栈帧2栈帧1线 ...

  8. java钟使用dwr_DWR中各种java方法的调用

    DWR是一个框架,简单的说就是能够在javascript直接调用java方法,而不必去写一大堆的javascript代码.它的实现是基于ajax的,可以实现无刷新效果. 网上有不少DWR的例子,但大都 ...

  9. java unlimited_具有无限参数的Java方法(Java method with unlimited arguments)

    具有无限参数的Java方法(Java method with unlimited arguments) Spring框架使用方法,您可以根据需要传递尽可能多的参数. 我想写一个函数,也可以采取无限量的 ...

最新文章

  1. Flask 模型操作
  2. CV之路——opencv基本操作
  3. 线性回归数据_数据科学笔记(三)——线性回归
  4. PermGen space处理方法1
  5. ElasticSearch里面关于日期的存储方式,解决差8个小时
  6. 【热门技术】三种SEO方式
  7. javaweb实训第六天下午——Mybatis基础
  8. 一起啃PRML - 1.2.1 Probability densities 概率密度
  9. Arcgis自带世界矢量图
  10. DIY一个VR小钢炮
  11. 帝国cms 7.5 wap标签大全
  12. 使用python根据图片链接下载图片
  13. 维修记录java_维修保养记录
  14. 电路知识--认识原理图(一)
  15. 丽江,清晨的小巷在哭泣
  16. 毛刺现象 java_硬件毛刺
  17. BigDecimal的ROUND_DOWN()中的坑
  18. java和python结合做项目_由浅入深Java+Python结合项目实战
  19. php仿qq聊天界面,jquery仿微信聊天界面
  20. 互联网从业必备-历史最全互联网黑话词汇表分享

热门文章

  1. SAP Spartacus API 的事务处理特性
  2. SAP Spartacus B2B 页面信息提示图标的弹出窗口显示实现逻辑
  3. Angular里的style property binding的一个例子
  4. Chrome开发者工具Element style里的Computed标签页
  5. 使用jasmine.createSpyObj具有依赖关系的Angular服务进行单元测试
  6. ABAP后台作业(background job)的几种状态
  7. odata协议里filter操作自带的函数 - endswith
  8. SAP UI5库对浏览器类型检测的实现
  9. Make Membership header extension fields editable
  10. check generated report by SE16