web-dev-qa-db-fra.com

la propriété lateinit n'a pas été initialisée

J'ai une classe linearlayout personnalisée et lorsque je veux créer une instance de cette classe, une erreur tarda la propriété n'a pas été initialisée J'utilise la dernière version de la bibliothèque butterknife

c'est ma classe de kotlin 

class MenuItemView : LinearLayout {

@BindView(R.id.menu_title_text_view_id)
lateinit var menuTitleTextView : CTextBasic

constructor(ctx: Context) : super(ctx) {
}

init {
    val view = LayoutInflater.from(context).inflate(R.layout.menu_item,this)
    ButterKnife.bind(this,view)
}

constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs) {
    val menuAttrs = context.theme.obtainStyledAttributes(attrs, R.styleable.MenuItemView, 0, 0)
    try {
        val title: String = menuAttrs.getString(R.styleable.MenuItemView_menu_title)
        menuTitleTextView.text = title
    }catch (e : Exception){
        e.printStackTrace()
    }finally {
        menuAttrs.recycle()
    }
}
fun setTitle( title : String){
    menuTitleTextView.text = title
}
}

c'est le journal des erreurs

    kotlin.UninitializedPropertyAccessException: lateinit property menuTitleTextView has not been initialized
at com.leavigstone.liberali.ui.custom.menu.MenuItemView.setTitle(MenuItemView.kt:48)
at com.leavigstone.liberali.ui.activities.MainActivity.onAddButtonClick(MainActivity.Java:142)
at com.leavigstone.liberali.ui.activities.MainActivity_ViewBinding$3.doClick(MainActivity_ViewBinding.Java:54)
at butterknife.internal.DebouncingOnClickListener.onClick(DebouncingOnClickListener.Java:22)
at Android.view.View.performClick(View.Java:4780)
at Android.view.View$PerformClick.run(View.Java:19866)
at Android.os.Handler.handleCallback(Handler.Java:739)
at Android.os.Handler.dispatchMessage(Handler.Java:95)
at Android.os.Looper.loop(Looper.Java:135)
at Android.app.ActivityThread.main(ActivityThread.Java:5254)
at Java.lang.reflect.Method.invoke(Native Method)
at Java.lang.reflect.Method.invoke(Method.Java:372)
at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:903)
at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:698)
15
Jemo Mgebrishvili

Si vous ne souhaitez utiliser aucune bibliothèque tierce partie, vous pouvez ajouter ces fonctions d'extension (j'ai tendance à avoir un ContextExtensions.kt ou ViewExtensions.kt pour les fonctions d'extension Context ou View related), puis l'insérer.

inline fun <reified T : View> View.find(id: Int): T = findViewById(id) as T
inline fun <reified T : View> Activity.find(id: Int): T = findViewById(id) as T
inline fun <reified T : View> Fragment.find(id: Int): T = view?.findViewById(id) as T

ils vous permettent d’appeler find depuis Activity, Fragment et Views . Ainsi, dans votre classe, au lieu de

@BindView(R.id.menu_title_text_view_id) lateinit var menuTitleTextView : CTextBasic

vous pouvez avoir

val menuTitleTextView by lazy { find<CTextBasic>(R.id.menu_title_text_view_id) }

Pour des éléments tels que les interfaces utilisateur, il est préférable de val au lieu de var lorsqu'ils ne nécessitent pas de modification. En règle générale en programmation, essayez de garder les choses aussi immuables que possible, vous obtiendrez beaucoup moins de bugs.

6
Billy

Utilisez Kotterknife pour Butter Knife-esque View Binding pour Kotlin.

Ensuite, vous pouvez lier votre vue avec

val menuTitleTextView: CTextBasic by bindView(R.id.menu_title_text_view_id)
2
lukle

Dans mon cas, je ne construisais pas ButterKnife correctement. Assurez-vous d’importer son compilateur dans le fichier build.gradle de votre module: 

...
// Butter Knife
implementation "com.jakewharton:butterknife:$butterKnifeVersion"
kapt "com.jakewharton:butterknife-compiler:$butterKnifeVersion"
...

La discussion sur les exemples de Jetbrain m'a permis de mieux comprendre ce problème. 

Un autre problème est que vous pouvez accéder aux vues avant le conteneur a été créé. Voici une question liée à , la discussion y est spécifique aux propriétés synthétiques de kotlinx mais la même logique devrait s’appliquer à la reliure de vue de Butterknife

0
kip2

ajoutez apply plugin: 'kotlin-kapt' au fichier build.gradle du niveau de l'application

exemple

apply plugin: 'com.Android.application'
apply plugin: 'kotlin-Android'
apply plugin: 'kotlin-Android-extensions'
apply plugin: 'kotlin-kapt'

et dans la section des dépendances

implementation "com.jakewharton:butterknife:8.8.1"
kapt "com.jakewharton:butterknife-compiler:8.8.1"

J'espère que cela t'aides!

0

J'ai trouvé cela fonctionne pour moi.

Changez votre build.gradle dans le module app de votre projet.

dependencies {
    compile "com.jakewharton:butterknife:8.8.1"
    kapt "com.jakewharton:butterknife-compiler:8.8.1"
}

utilisez kapt au lieu de annotationProcessor.

et ensuite vous pouvez faire votre annotation ButterKnife familière comme ceci:

class MainActivity : AppCompatActivity() {

    @BindView(R.id.myButton)
    lateinit var myButton: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        ButterKnife.bind(this)
        //...
    }
}

Prendre plaisir.

0
Johnny