Daniel Wilson
Daniel Wilson

Reputation: 19824

Android Gradle Plugin 3.5.1 databinding error with Kotiln Generic type

I am in the middle of trying to modularize a library so tbh anything could be going on here. After updating from the Android Gradle Plugin 3.5.0 to 3.5.1, I now get a databinding error on a layout which uses my Resource.kt class. The class I believe was lifted straight out of the Google Github Browser sample (I can't get the latest commit of that to build at all for some reason). The error seems to be specifically with the generic data field T.

Resource.kt

data class Resource<out T>(val status: Status, val data: T?, val message: String?, val throwable: Throwable? = null) {
    companion object {
        fun <T> success(data: T?): Resource<T> {
            return Resource(SUCCESS, data, null)
        }

        fun <T> error(data: T?, msg: String, throwable: Throwable?): Resource<T> {
            return Resource(ERROR, data, msg, throwable)
        }

        fun <T> loading(data: T?): Resource<T> {
            return Resource(LOADING, data, null)
        }
    }
}

Layout xml:

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <import type="android.view.View" />

        <import type="core.sdk.data.remote.response.Resource" />

        <import type="core.sdk.data.remote.response.Status" />

        <variable
            name="resource"
            type="Resource" />

        <variable
            name="progressText"
            type="String" />
    </data>

    <LinearLayout
        android:id="@+id/circular_progress"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:gravity="center"
        android:orientation="vertical"
        app:visibleGone="@{resource.data == null}">

        <androidx.core.widget.ContentLoadingProgressBar
            android:id="@+id/progress_bar"
            style="@style/Widget.AppCompat.ProgressBar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:indeterminateTint="@color/ll_secondary"
            android:indeterminateTintMode="src_in"
            app:visibleGone="@{resource.status == Status.LOADING}"
            tools:ignore="UnusedAttribute" />

        <TextView
            android:id="@+id/progress_text_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:text="@{progressText}"
            android:textAppearance="?attr/textAppearanceHeadline5"
            android:textColor="@color/ll_secondary"
            android:textStyle="italic"
            app:visibleGone="@{resource.status == Status.LOADING}"
            tools:text="loading..." />
    </LinearLayout>

</layout>

Error:

LoadingStateBindingImpl.java:106: error: ';' expected ? resourceData = null; enter image description here

I have incremental databinding and kapt on:

android.databinding.incremental=true
kapt.incremental.apt=true

Project is a fully Kotlin using Kotlin 1.3.50 with a jvm target of 1.8:

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

kotlinOptions {
    jvmTarget = "1.8"
}

This error does not appear with AGP 3.5.0. Here is the same file with 3.5.0 and no error:

enter image description here

Upvotes: 5

Views: 689

Answers (2)

goemic
goemic

Reputation: 1339

As @enyciaa noted, you need to specify (more) explicitly the type of Resource<?> for your variable int the layout's <data>..</data>.

In your example it means the following:

<data>
        ..
        <variable
        name="resource"
        type="Resource&lt;java.lang.Object>" />
</data>

Upvotes: 0

enyciaa
enyciaa

Reputation: 2122

This is unfortunately a change to how databinding works, and judging from the issue tracker discussion this is a permanent change.

Databinding references are now a bit stricter, so using a generic class - in this case Resource - will fail. Similarly using something like List:

<variable name="list" type="java.util.List"/>

will also fail. Because databinding doesn't have enough information to work out what the generic type is - someone with more knowledge of generics may be able to explain why this is the case!

In order to handle the generics, Databinding needs more information. There's two ways to update databinding to work with the new gradle plugin:

  1. Directly define your generic. "&lt" is the xml equivalent to "<".
<variable name="list" type="java.util.List&lt;MyClass>"/>
  1. Wrap your generic in a containing class.
class MyGenericWrapper : List<Object>  

<variable name="myVariable" type="MyGenericWrapper"/>

Upvotes: 1

Related Questions