Ok, I've been tasked with migrating a project to AndroidX to reduce the clutter of the support libs in our project. I've enabled AndroidX as per the official docs but now I'm getting run time errors when trying to inflate views via the corresponding auto generated Binding classes that are created from enabling databinding in the modules gradle.
Digging into the autogenerated source I came across this method, which is the one which is causing the code to throw:
public List<DataBinderMapper> collectDependencies() {
ArrayList<DataBinderMapper> result = new ArrayList(1);
result.add(new com.android.databinding.library.baseAdapters.DataBinderMapperImpl());
return result;
}
As you can see, the auto generated code is attempting to instantiate an class from the com.android.databinding
package, but that package doesn't exist in the output APK as I have removed the support dependencies from my gradle (because AndroidX is supposed to replace them). I can see that androidx has a databinding package so I am assuming that the autogenerated code above should be referencing androidx.databinding package instead, but it doesn't.
Is this a bug in the tooling or have I misconfigured something?
Here is my gradle file (some bits omitted for security reasons):
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
//These variable refer to release builds so make sure they are correct. If you need to override them
//for some specific development needs then use variables that can be passed to gradle on command line.
String releaseVersionName = '1.0.0'
int releaseVersionCode = 1
int releaseMinSdk = 18
int releaseCompileSdkVersion = 28
android {
//Added as separate variable so it can be overridden from IDE to speed up compilation time
//Set minimum compilation sdk.
int developMinSdk = rootProject.hasProperty('productMinSdk') ?
rootProject.productMinSdk.toInteger() : releaseMinSdk
String developProductVersionName = rootProject.hasProperty('productVersionName') ?
rootProject.productVersionName : releaseVersionName
int developProductVersionCode = System.getenv("BUILD_ID") as Integer ?: releaseVersionCode
int developCompileSdk = rootProject.hasProperty('productCompileSdk') ?
rootProject.productCompileSdk.toInteger() : releaseCompileSdkVersion
defaultConfig {
applicationId "..."
compileSdkVersion developCompileSdk
minSdkVersion developMinSdk
targetSdkVersion developCompileSdk
versionCode developProductVersionCode
versionName developProductVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
signingConfigs {
...
}
sourceSets {
...
}
buildTypes {
debug {
signingConfig signingConfigs.release
dexOptions {
jumboMode = true
javaMaxHeapSize "1g"
}
multiDexEnabled true
matchingFallbacks = ['debug', 'release']
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
dexOptions {
jumboMode = true
javaMaxHeapSize "1g"
}
}
}
flavorDimensions "default"
productFlavors {
//noinspection GroovyMissingReturnStatement
develop {
applicationIdSuffix ".develop"
dimension "default"
sourceSets {
develop.java.srcDirs += 'src/develop/kotlin'
}
}
//Normal build for release
//noinspection GroovyMissingReturnStatement
playstore {
//In this flavour we use release* variable explicitly so they cannot be
//overridden by mistake
//Force min sdk version from the global variable
minSdkVersion releaseMinSdk
//Force version name from the global variables
versionName releaseVersionName
//Force version code from the global variable
versionCode releaseVersionCode
//Force compile and target sdk versions from the global variable
compileSdkVersion releaseCompileSdkVersion
targetSdkVersion releaseCompileSdkVersion
dimension "default"
sourceSets {
playstore.java.srcDirs += 'src/playstore/kotlin'
}
}
}
dataBinding {
enabled = true
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// Runtime dep versions
def condecoCoreVersion = "0.1.3"
def appCenterVersion = "1.9.0"
def thirtyinchVersion = '0.9.0'
def stethoVersion = "1.5.0"
def leakCanaryVersion = '1.5.4'
def hahaVersion = "1.3"
def multiDexVersion = "2.0.0"
def constraintLayoutVersion = "1.1.3"
// Test dep versions
def jUnitVersion = "4.12"
// Std lib dependency
implementation group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8', version: "$kotlin_version"
implementation group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: "$kotlin_version"
// Multidex dependency
implementation "androidx.multidex:multidex:$multiDexVersion"
// Junit dependency for testing
testImplementation "junit:junit:$jUnitVersion"
}
And here is my gradle.properties file:
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
# Use androidX to replace requirement for
# Support libraries to be imported via gradle
android.useAndroidX=true
# Jetifier automatically updates dependancy binaries
# To swap out support lib for androix
android.enableJetifier=true
EDIT: And here is my project level gradle:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext {
kotlin_version = '1.2.71'
gradle_plugin_version = '3.2.1'
}
repositories {
google()
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:$gradle_plugin_version"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
Recently Android has announced that with Kotlin 1.4. 20, their Android Kotlin Extensions Gradle plugin will be deprecated and will no longer be shipped in the future Kotlin releases. Android Kotlin Extensions plugin brought with it two very cool features : Synthetics let you replace calls to findViewById with kotlinx.
Using data binding can lead to faster development times, faster execution times and more readable and maintained code. Android data binding generates binding classes at compile time for layouts.
The Data Binding Library is a support library that allows you to bind UI components in your layouts to data sources in your app using a declarative format rather than programmatically. Layouts are often defined in activities with code that calls UI framework methods.
Ok, finally cracked this.
The issue was I was using a library which depended on android databinding (and not androidx databinding).
Even though I had enabled Jetifier in my gradle.properties
file, for some reason the libraries binary wasn't having android databinding swapped out for the corresponding androidx version. Fortunately, the library was in house, so I've updated the library to migrate to androidx and this whole nightmare resolved itself.
Thanks for all the suggestions, hope this answer helps anyone with a similar problem as it's cost me 2 working days to figure out!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With