简体   繁体   中英

Kotlin + Databinding throw no viable alternative at input '??'

Please excuse my poor English.

I'm using AndroidStudio3.1.1, I've tried to use data binding my project with kotlin , but I get an error when I'm trying to run the project. The error message that I'm getting is like below:

e: [kapt] An exception occurred: android.databinding.tool.util.LoggedErrorException: Found data binding errors. ****/ data binding error ****msg:Syntax error: no viable alternative at input '??' file:/Users/eraise/Code/Demo/app/src/main/res/layout/layout_main.xml loc:20:28 - 20:64 ****\\ data binding error ****

I can compile apk on Terminal due command: ./gradlew assembleDebug, that works fine.

My top-level build.gradle has this configuration:

buildscript {
ext.kotlin_version = '1.2.31'
repositories {
    google()
    jcenter()
}
dependencies {
    classpath 'com.android.tools.build:gradle:3.1.1'
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        maven { url 'https://www.jitpack.io'}
    }
}

My build.gradle in app dir (only relevant parts):

apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
android{
    compileSdkVersion 27
    buildToolsVersion 27.1.0
    dataBinding {
        enabled = true
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}
dependencies {
    kapt "com.android.databinding:compiler:3.1.1"
}

My layout_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<layout>

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

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  xmlns:app="http://schemas.android.com/apk/res-auto"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:orientation="vertical">

        <TextView
            android:id="@+id/tv_version_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text='@{"测试" + version??"unknow", default=版本号}'
            />

        <android.support.v7.widget.RecyclerView
            android:id="@+id/rv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#EEE"                    
            app:layoutManager="android.support.v7.widget.LinearLayoutManager"
            />

    </LinearLayout>
</layout>

Error on the line: android:text='@{"测试" + version??"unknow", default=版本号}'

LayoutMainBinding snippet:

@Override
protected void executeBindings() {
    long dirtyFlags = 0;
    synchronized(this) {
        dirtyFlags = mDirtyFlags;
        mDirtyFlags = 0;
    }
    java.lang.String version = mVersion;
    java.lang.String javaLangStringVersion = null;
    java.lang.String javaLangStringVersionJavaLangObjectNullJavaLangStringUnknowJavaLangStringVersion = null;
    boolean javaLangStringVersionJavaLangObjectNull = false;

    if ((dirtyFlags & 0x3L) != 0) {


            // Here's ?????? is 测试 if correct result.
            // read ("??????") + (version)
            javaLangStringVersion = ("??????") + (version);


            // read ("??????") + (version) == null
            javaLangStringVersionJavaLangObjectNull = (javaLangStringVersion) == (null);
        if((dirtyFlags & 0x3L) != 0) {
            if(javaLangStringVersionJavaLangObjectNull) {
                    dirtyFlags |= 0x8L;
            }
            else {
                    dirtyFlags |= 0x4L;
            }
        }
    }
    // batch finished

    if ((dirtyFlags & 0x3L) != 0) {

            // read ("??????") + (version) == null ? "unknow" : ("??????") + (version)
            javaLangStringVersionJavaLangObjectNullJavaLangStringUnknowJavaLangStringVersion = ((javaLangStringVersionJavaLangObjectNull) ? ("unknow") : (javaLangStringVersion));
    }
    // batch finished
    if ((dirtyFlags & 0x3L) != 0) {
        // api target 1

        android.databinding.adapters.TextViewBindingAdapter.setText(this.tvVersionName, javaLangStringVersionJavaLangObjectNullJavaLangStringUnknowJavaLangStringVersion);
    }
}

I can run correct if do not use kotlin

I think the problem is with the braces. Try to do it this way:

@{"test" + (user.name??"unknow", default=versionnumber)}'

I think you set the wrong expression for

android:text='@{"测试" + version??"unknow", default=版本号}'

I mean, what are you trying to achieve with this? Is it if version is null then return "unknown", and if it's not, return 版本号? I think also because you didn't use "" (double quotes) in your 版本号

If you want to express it that way, try this one:

android:text='@{"测试" + (version != null ? "版本号" : "unknown")}'

Expected Result

If version != null -> 测试版本号

If version == null -> 测试unknown

I tried and it works! But if the expected result is not what you want, let me know and we can work around it.

This problem cause by kapt not works well with Chinese character. So replace them with English or set your computer env as below:

JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF8

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM