skip to Main Content

I am working one project using kotlin + Rxjava + MVVM. During development facing issue of importing view ids in Fragment or viewholder.

import kotlinx.android.synthetic.main.layout.* unused with kotlin.

kotling synthetic imports is unused

Normaly view id should used from kotlin synthetic layout imports but it directly import it from R.id that should not happen.

Kotlin plugin version : org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.40

My gradle file :

apply plugin: 'com.android.feature'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'idea'
apply plugin: 'kotlin-kapt'

android {
    compileSdkVersion 27
    baseFeature true
    defaultConfig {
        minSdkVersion 23
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }


    lintOptions {
        abortOnError false
    }
}

dependencies {

    api "com.android.support:design:$rootProject.support_library_version"
    api "com.android.support:appcompat-v7:$rootProject.support_library_version"
    api "com.android.support:recyclerview-v7:$rootProject.support_library_version"
    api "com.android.support:support-dynamic-animation:$rootProject.support_library_version"
    api "com.android.support:cardview-v7:$rootProject.support_library_version"
    api "com.android.support:customtabs:$rootProject.support_library_version"

    api "com.android.support.constraint:constraint-layout:1.1.0-beta5"
    api 'android.arch.lifecycle:extensions:1.1.0'


    api 'androidx.core:core-ktx:0.2'


    api "com.google.dagger:dagger:$rootProject.dagger_version"
    kapt "com.google.dagger:dagger-compiler:$rootProject.dagger_version"

    api "android.arch.persistence.room:runtime:$rootProject.room_version"
    kapt "android.arch.persistence.room:compiler:$rootProject.room_version"
    testImplementation "android.arch.persistence.room:testing:$rootProject.room_version"
    api "android.arch.persistence.room:rxjava2:$rootProject.room_version"
    androidTestImplementation "android.arch.core:core-testing:$rootProject.room_version"
    testImplementation "android.arch.core:core-testing:$rootProject.room_version"

    api "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    api "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"


    api 'com.jakewharton.timber:timber:4.5.1'

    api "com.android.support:multidex:1.0.3"

    api "com.github.bumptech.glide:glide:$rootProject.glide_version"
    api "jp.wasabeef:glide-transformations:$rootProject.glide_transformation_version"
    api 'com.github.bumptech.glide:okhttp3-integration:1.5.0@aar'

    api "io.reactivex.rxjava2:rxandroid:$rootProject.rxAndroid_version"
    api "io.reactivex.rxjava2:rxjava:$rootProject.rxJava_version"
    api "com.google.code.gson:gson:$rootProject.gson_version"

    api("com.squareup.retrofit2:retrofit:$rootProject.retrofit_version") {
        // exclude Retrofit’s OkHttp peer-dependency module and define your own module import
        exclude module: 'okhttp'
    }

    api "com.squareup.okhttp3:okhttp:$rootProject.okhttp_version"
    api "com.squareup.okhttp3:logging-interceptor:$rootProject.okhttp_version"
    api "com.squareup.retrofit2:adapter-rxjava2:$rootProject.retrofit_version"
    api "com.squareup.retrofit2:converter-gson:$rootProject.retrofit_version"

    api 'com.jakewharton.threetenabp:threetenabp:1.0.5'

    api "com.google.firebase:firebase-invites:$rootProject.play_services_version"
    api "com.google.firebase:firebase-core:$rootProject.play_services_version"
    api "com.google.firebase:firebase-config:$rootProject.play_services_version"
    api "com.google.firebase:firebase-perf:$rootProject.play_services_version"
    api "com.google.firebase:firebase-auth:$rootProject.play_services_version"
    api "com.google.firebase:firebase-firestore:$rootProject.play_services_version"



    api("com.firebaseui:firebase-ui-auth:$rootProject.firebase_ui_version") {
        // exclude Retrofit’s OkHttp peer-dependency module and define your own module import
        exclude module: 'play-services-auth'
        exclude module: 'firebase-auth'
    }

    // Required only if Facebook login support is required
    api('com.facebook.android:facebook-android-sdk:4.31.0')

    api "com.google.android.gms:play-services-auth:$rootProject.play_services_version"

    // Required only if Twitter login support is required
    api("com.twitter.sdk.android:twitter-core:3.0.0@aar") { transitive = true }

    api 'com.jakewharton.rxbinding2:rxbinding-kotlin:2.0.0'
    api 'com.jakewharton.rxbinding2:rxbinding-support-v4-kotlin:2.0.0'
    api 'com.jakewharton.rxbinding2:rxbinding-appcompat-v7-kotlin:2.0.0'
    api 'com.jakewharton.rxbinding2:rxbinding-design-kotlin:2.0.0'

    api('com.crashlytics.sdk.android:crashlytics:2.9.1@aar') {
        transitive = true
    }
}

I have also tried clean build and Rebuild project.

Any idea how can i resolve this issue ?

10

Answers


  1. I have the same problem and I am trying to solve it for too many days…

    One trick you can do is to Exclude from Import and Completion <package-name>.R.id.* for project scope.

    Go to Settings/Editor/Auto Import to add it.

    It improves our issue and if you do this and clean the project, it will work but it does not resolve the issue completely. Many times the imports reappear as unused imports and there is to clean the project over and over :-(.

    EDITED

    Also, another improvement I have achieved is working with includes on XML. For example, if I am going to use “the same” button in several screens, I make a specific layout for this button and I re-use it on several activities / fragments. You can set the id within this specific layout and synthetic will auto-import it without generating conflicts, due to you have the content view reference declared before.

    I show you a simple example:

    activity_main.xml

    <!-- ... -->
    
    <include layout="@layout/btn_foo"/>
    
    <!-- ... -->
    

    btn_foo.xml

    <?xml version="1.0" encoding="utf-8"?>
    <Button
        android:id="@+id/btnFoo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        xmlns:android="http://schemas.android.com/apk/res/android"/>
    

    MainActivity.kt

    // ...
    
    import kotlinx.android.synthetic.main.activity_main.*
    import kotlinx.android.synthetic.main.btn_foo.*
    
    // ...
    
    setContentView(R.layout.activity_main)
    
    // ...
    
    btnFoo.setOnClickListener { }
    

    I have to admit that in the other cases I have returned to the typical Hungarian convention whatWhereDescription(Size) to set the ids due to is too much annoying to deal with imports among activities / fragments / view all the time.

    Login or Signup to reply.
  2. I have tried several approaches including the solutions reported in this thread. I also found out that a lot of folks are facing this annoying problem as you can see here

    Nevertheless, the most closest solution to this problem which has worked for me so far is removing apply plugin: kotlin-android-extensions from gradle, Sync gradle plugin and then add it again.

    Login or Signup to reply.
  3. I’m using Android Studio 3.1.3 and I encountered the same issue. I managed to solve this by moving all my codes from java/ to kotlin/ directory inside main/.

    app/
     |-- src/
     |    |-- main/
     |    |    |-- java/
     |    |    |     |-- com.example.android.app
     |    |    |-- kotlin/  <-- (use this)
     |    |    |     |-- com.example.android.app
    

    Then, add the kotlin/ as part of the source sets:

    app/build.gradle

    android {
       sourceSets {
           main.java.srcDirs += 'src/main/kotlin'
       }
    }
    

    Sometimes, it still requires to sync and rebuild the project to properly import the kotlinx.android....

    Reference: Add kotlin code

    Login or Signup to reply.
  4. There is an existing issue (which is assigned) on Google tracker regarding synthetic imports.
    https://issuetracker.google.com/issues/78547457

    Login or Signup to reply.
  5. I don’t know if this tripped anyone else up, but I was having problems because I didn’t realize the synthetic objects are only available if you’re inside an Activity, Dialog, or Fragment. If you’re in some other class (like using Conductor‘s Controller) you’re out of luck.

    Login or Signup to reply.
  6. I’ve solved similar issues for ViewHolder implementations:

    We have to inherit our ViewHolder class implementation from LayoutContainer. LayoutContainer is an interface available in kotlinx.android.extensions package.

    You will have some code similar with this:

    class TaskVH(override val containerView: View, val itemListener: TasksFragment.TaskItemListener) : RecyclerView.ViewHolder(containerView), LayoutContainer {
        fun bindItem(task: Task) {
            item_title.text = ""
            item_complete.isChecked = task.isCompleted
            itemView.setBackgroundResource(rowViewBackground)
            itemView.setOnClickListener { itemListener.onTaskClick(task) }
        }
    }
    
    Login or Signup to reply.
  7. For Conductor:

    Create this base class.

    import android.os.Bundle
    import android.view.View
    import com.bluelinelabs.conductor.Controller
    import com.bluelinelabs.conductor.RestoreViewOnCreateController
    
    abstract class BaseController(
            bundle: Bundle? = null
    ) : RestoreViewOnCreateController(bundle){
    
        init {
            addLifecycleListener(object : LifecycleListener() {
                override fun postCreateView(controller: Controller, view: View) {
                    onViewCreated(view)
                }
            })
        }
    
        open fun onViewCreated(view: View) { }
    
    }
    

    Then in your controller:

    import kotlinx.android.synthetic.main.controller_example.view.*
    
    class ProfileController : BaseController() {
    
        override fun onCreateView(inflater: LayoutInflater, container: ViewGroup, savedViewState: Bundle?): View {
            return inflater.inflate(R.layout.controller_example, container, false)
        }
    
        override fun onViewCreated(view: View) {     
            view.txtName.text = "Example"
        }
    
    }
    
    Login or Signup to reply.
  8. Cross-posting my bug report with workaround from here: https://issuetracker.google.com/issues/145888144

    Original bug was closed as "fixed" by google, but it is definitely not fixed: https://issuetracker.google.com/issues/78547457

    SUMMARY:

    For some modules in a multi-module project, the IDE does not properly recognize imports for "synthetic" symbols that abstract view ids, a feature provided by the plugin ‘kotlin-android-extensions’. This results in class files using these symbols appearing full of errors, as the imports are "unresolved", the symbols are then unknown, and of course anything using these symbols fail because the types are unknown.This is solely an IDE problem though; everything compiles normally and works as expected.

    ROOT CAUSE

    The kotlin-language facet is not being applied to the errant modules.

    BACKGROUND

    Facets in IntelliJ IDEA projects are configurable on a module-by-module basis in Project settings. In Android Studio, this part of the Project settings UI is missing (or suppressed.) Presumably, Android Studio is attempting to apply the correct facets based on the gradle plugins applied to each module. This process is /sometimes/ FAILING for this particular case; I have not been able to determine what triggers the success/failure of the process.

    TEMPORARY WORKAROUND

    This workaround works consistently, and has since 3.5.2 when I discovered it:

    1. Open the ".iml" file for the module you are trying to "fix" in Android Studio editor. (In AS > 4, the iml file is in .idea/modules, earlier than that it was in top-level of your module.) Find the <component name="FacetManager"> block, and notice that there is no facet called "kotlin-language" there. Paste the contents of the text block below so it appears within the <component name="FacetManager"> block. Save the file.
    2. Re-import gradle.

    This is a clumsy workaround, and has to be applied on a module-by-module basis. What’s more, it may be required to sometimes re-apply the workaround after making changes to the build.gradle file for an affected module. The hope is that Google (or JetBrains, if it turns out it is their problem) will fix this problem properly.

    Given that kotlin-android-extensions has fallen out of favor, I don’t expect this bug will ever be fixed.

    Text to use for the fix

        <facet type="kotlin-language" name="Kotlin">
          <configuration version="3" platform="JVM 1.8" allPlatforms="JVM [1.8]" useProjectSettings="false">
            <compilerSettings />
            <compilerArguments>
              <option name="jvmTarget" value="1.8" />
              <option name="pluginOptions">
                <array>
                  <option value="plugin:org.jetbrains.kotlin.android:enabled=true" />
                  <option value="plugin:org.jetbrains.kotlin.android:defaultCacheImplementation=hashMap" />
                </array>
              </option>
            </compilerArguments>
          </configuration>
        </facet>
    
    Login or Signup to reply.
  9. I try every other solution bu no one worked for me. At the and I cloned project again and now it’s working. I love android studio

    Login or Signup to reply.
  10. Add id kotlin-android-extensions in your build.gradle file in the plugins block.

    Google removed this feature by default

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search