Je travaille sur un projet utilisant kotlin + Rxjava + MVVM. Au cours du développement, il était difficile d'importer des identifiants de vue dans Fragment ou viewholder.
import kotlinx.Android.synthetic.main.layout.*
non utilisé avec kotlin.
Normalement, l'identifiant de vue doit être utilisé dans les importations de présentations synthétiques de Kotlin, mais il importe directement dans R.id, ce qui ne devrait pas se produire.
Version du plugin Kotlin: org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.40
Mon fichier de notes:
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
}
}
J'ai également essayé de construire et de reconstruire le projet.
Toute idée de comment puis-je résoudre ce problème?
J'utilise Android Studio 3.1.3 et j'ai rencontré le même problème. J'ai réussi à résoudre ce problème en déplaçant tous mes codes de Java/
dans le répertoire kotlin/
à l'intérieur de main/
.
app/
|-- src/
| |-- main/
| | |-- Java/
| | | |-- com.example.Android.app
| | |-- kotlin/ <-- (use this)
| | | |-- com.example.Android.app
Ensuite, ajoutez le kotlin/
dans les ensembles de sources:
app/build.gradle
Android {
sourceSets {
main.Java.srcDirs += 'src/main/kotlin'
}
}
Parfois, il faut encore synchroniser et reconstruire le projet pour importer correctement le kotlinx.Android....
Référence: Ajouter le code kotlin
J'ai essayé plusieurs approches, y compris les solutions présentées dans ce fil. J'ai aussi découvert que beaucoup de gens font face à ce problème gênant, comme vous pouvez le constater ici
Néanmoins, la solution la plus proche de ce problème qui a fonctionné pour moi jusqu’à présent consiste à supprimer le plug-in apply plugin: kotlin-Android-extensions
de gradle, Sync
gradle, puis de l'ajouter à nouveau.
J'ai le même problème et j'essaie de le résoudre pendant trop de jours ...
Une astuce que vous pouvez faire est de Exclure de l’importation et de l’achèvement <package-name>.R.id.*
pour la portée du projet.
Allez à Settings/Editor/Auto Import
pour l'ajouter.
Cela améliore notre problème et si vous faites cela et nettoyez le projet, cela fonctionnera mais cela ne résoudra pas le problème complètement. Plusieurs fois, les importations réapparaissent sous la forme importations non utilisées et il est nécessaire de nettoyer le projet encore et encore :-(.
&EACUTE;DIT&EACUTE;
En outre, une autre amélioration que j'ai obtenue consiste à utiliser include
s sur XML. Par exemple, si je vais utiliser "le même" bouton sur plusieurs écrans, je crée un agencement spécifique pour ce bouton et je le réutilise sur plusieurs activités/fragments. Vous pouvez définir l'identifiant dans cette présentation spécifique et Synthetic l'importera automatiquement sans générer de conflits, car la référence de vue de contenu a déjà été déclarée.
Je vous montre un exemple simple:
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 { }
Je dois admettre que dans les autres cas je suis revenu à à la convention hongroise typique whatWhereDescription (Size) pour définir le id
s en raison de la gêne occasionnée pour traiter les importations entre activités/fragments/afficher tout le temps.
Je ne sais pas si cela a fait trébucher quelqu'un d'autre, mais j'avais des problèmes, car je n'avais pas réalisé que les objets synthétiques n'étaient disponibles que si vous vous trouviez dans un Activity
, Dialog
ou Fragment
. Si vous êtes dans une autre classe (par exemple, avec Conductor 's Controller
), vous n’avez pas de chance.
Un problème existant (affecté) sur Google Tracker concernant les importations synthétiques . https://issuetracker.google.com/issues/78547457
J'ai résolu des problèmes similaires pour les implémentations de ViewHolder:
Nous devons hériter de notre implémentation de classe ViewHolder de LayoutContainer. LayoutContainer est une interface disponible dans le package kotlinx.Android.extensions.
Vous aurez un code similaire avec ceci:
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) }
}
}
Pour chef d'orchestre:
Créez cette classe de base.
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) { }
}
Puis dans votre contrôleur:
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"
}
}