65535 java_Databinding引起的 java方法大于 65535 的问题
# Databinding引起的 java方法大于 65535 的問題
## 前言
項目中開發使用的是 MVVM 開發模式,并且選擇了 Databinding 作為 ViewModel 和 View之間通信的橋梁,再加上一定的封裝,使用起來是挺方便的,但是也會遇到一些坑,比如我遇到的這個:
**Databinding 生成的 Java 文件中方法大于 65535 問題。**
如下圖所示:

## 緣由
這個問題是怎么來的呢?
其實觸發條件挺小的,只有在特定的情況下才會遇到,要滿足下面的條件:
1. 使用 Databinding
2. 項目要是中大型的項目(使用 Databinding 的xml文件多)
3. gradle 插件的版本要小于 3.2.0
## 模擬發生
新建項目,然后新建一個 Module:lib2,項目結構如圖所示

然后分別在 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各)。
這個時候應該就會見到這個錯誤了:

我們看下這個報錯的 DatabinderMapperImpl :

> ps:你的可能和我的不一樣,xml 文件個數可能不同。
可以看到總共就那幾個方法,卻有2萬多行代碼,其中第一個 getDataBinder 方法很長,大概有15368 行,根據錯誤提示,可以初步斷定就是就是這里的方法太大了,超過了 65535 的限制。

可以看到這個 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.
執行編譯:

可見這里已經執行成功了。我們再來看下剛才 app - build 下面出錯的 DataBinderMapperImpl 文件:

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

可以看到,在新版本的 DataBinderMapperImpl 的 getDataBinder 方法中,google 已經把獲取 ViewDataBinding 的操作進行了拆分,使用 internalGetViewDataBindingXX 對所有的 layout 文件進行分組,每個組建立了 50 個映射關系,比如 internalGetViewDataBinding0 的代碼如下:

裝對 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 的问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中国联通现拥有 117 万 5G 基站,
- 下一篇: 酷狗音乐状态栏歌词怎么变大