Disabling Kotlin synthetic bindings when using Android data binding
Asked Answered
D

1

8

I'm working through this Udacity course on Android/Kotlin/KTX. The "About Me" application introduces data binding, while the Android team seems to advise against using KTX binding. So I would like to do the former instead of the latter.

However, things are not going as expected. These are the weird problems I face:

  1. On my first pass through, I was unable to get Android Studio to recognize any of my R.id.viewName IDs. Typing R.id. would give me all sorts of options, such as R.id.action_bar, but none from my activity. At some point this cleared up.
  2. The editor complained about unresolved references for the data binding classes up until I built the thing (e.g. lateinit var binding: ActivityMainBinding). Actually, I'm thinking it took more than one build, possibly getting fixed as a result of my mucking about elsewhere (see below).
  3. Each view ID is still being generated as a global variable containing the view object of that ID. That is, if I have a button with ID doneButton, I can reference it in the code as the synthetic doneButton just by importing it. I assume that means the objects are always built at run-time, even though I don't plan to use them. How do I make these KTX-style bindings go away?

Here is my build gradle:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    ext.kotlin_version = '1.3.31'
    repositories {
        google()
        jcenter()

    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.4.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()

    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

Here is my module gradle:

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.example.android.aboutme"
        minSdkVersion 19
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    dataBinding {
        enabled = true
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

While searching around the net for a way to get the data binding classes generated, I discovered a possible need to include the following line in gradle.properties:

android.databinding.enableV2=true

I rebuilt after doing so, and voila!, the classes finally built. So I was getting ready to send feedback about missing bits to Udacity, when I decided that I better make sure I understood what really fixed the problem. So after successfully running the program, I removed the above gradle.properties line, cleaned and rebuilt the project. To my surprise, it still built and ran.

So I have no idea what fixed the problem or how to resolve these issues in the next project.

I would also like to prevent all the global KTX binding classes from being instantiated, and I'm still clueless about how to do that.

Another SO answer claims to provide two solutions to the problem of generating binding classes, but the solutions given are for 2016 and 2017, and the above gradle files are presently working (generating the binding classes) despite not implementing those solutions, so there's clearly a newer way.

Thanks for any help you can offer! (Oh, I should also mention that I'm using a fully-updated Android Studio version 3.4.)

UPDATE 1: I'm making some progress. It appears that the Android Studio 3.4 code editor is the only thing not recognizing the generated data binding classes. The classes are recognized again upon rebuilding but recognition is lost on cleaning. I'm not yet sure this understanding resolves all of my issues...

UPDATE 2: This is (at least in part) an Android Studio bug that was fixed in March, due for Canary 7.

Discountenance answered 12/5, 2019 at 21:40 Comment(6)
Regarding disabling Kotlin synthetic accessors, you could try stackoverflow.com/a/55643236. "while the Android team seems to advise against using KTX binding" -- Google has neither endorsed nor advised against it (see this for example).Vesicle
Thank you. I failed to find that SO question, but the answer fails to change anything.Discountenance
If you are not using @Parcelize (or things that depend on it), you could remove apply plugin: 'kotlin-android-extensions', as that is the plugin that is generating the synthetic accessors.Vesicle
That worked! I guess there's not much more to the Kotlin extensions, huh? I wonder why Android Studio 3.4 is added them to projects by default.Discountenance
Did you find an answer how to disable kotlin synthetics? I'd also like to disable them in my project as they cause all kinds of runtime errors.Proffitt
Sorry @IgorGanapolsky, I never got further than this, and I'm off writing a Flutter app now.Discountenance
S
0

In order to disable Kotlin Synthetic access, from the app level build.gradle file remove the plugin kotlin-android-extensions. This plugin generates synthetic imports.

Sudoriferous answered 14/5, 2021 at 11:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.