свойство lateinit не было инициализировано

У меня есть собственный класс linearlayout, и когда я хочу создать экземпляр этого класса, я получаю следующую ошибку:
Свойство lateinit не было инициализировано

Я использую последнюю версию библиотеки Butterknife.

Вот мой класс 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
}
}

Журнал ошибок

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)

person Jemo Mgebrishvili    schedule 21.10.2016    source источник


Ответы (8)


Если вы не хотите использовать какие-либо сторонние библиотеки, вы можете добавить эти функции расширения (я обычно использую ContextExtensions.kt или ViewExtensions.kt для функций расширения, связанных с контекстом или представлением), а затем вставьте их

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

они позволяют вызывать find из Activity, Fragment и Views. Итак, внутри вашего класса вместо

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

вы можете иметь

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

Для таких вещей, как пользовательский интерфейс, лучше val вместо var, когда их не нужно менять. Как общее правило в программировании, старайтесь, чтобы вещи оставались неизменными, насколько это возможно, вы получите гораздо меньше ошибок.

person Billy    schedule 23.05.2017

Я обнаружил, что это работает для меня.

Измените свой build.gradle в app модуле вашего проекта.

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

используйте kapt вместо annotationProcessor.

а затем вы можете сделать свою знакомую аннотацию ButterKnife следующим образом:

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)
        //...
    }
}

Наслаждаться.

person Johnny    schedule 11.01.2018
comment
это единственное правильное решение, вы, вероятно, найдете свое собственное имя с помощью компиляции com.jakewharton: butterknife: 8.8.1, но вы обнаружите, что ur gradle отсутствует kapt com.jakewharton: butterknife-compiler: 8.8.1 - person Mohammad Elsayed; 23.04.2019

добавить apply plugin: 'kotlin-kapt' в файл build.gradle уровня приложения

пример

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

и в разделе зависимостей

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

Надеюсь это поможет!

person Lakshan Dissanayake    schedule 06.10.2018
comment
На этом этапе я обнаружил следующую ошибку: :app:kaptGenerateStubsDebugKotlin - ›Данный артефакт содержит строковый литерал со ссылкой на пакет« android.support.v4.content », которую нельзя безопасно переписать. Библиотеки, использующие отражение, такие как процессоры аннотаций, необходимо обновлять вручную, чтобы добавить поддержку androidx. - person Aliton Oliveira; 26.01.2020
comment
Я решил это, следуя этим инструкциям: github.com/JakeWharton/butterknife - person Aliton Oliveira; 26.01.2020

Используйте Kotterknife для привязки вида Butter Knife для Kotlin.

Затем вы можете связать свой View с помощью

val menuTitleTextView: CTextBasic by bindView(R.id.menu_title_text_view_id)
person Lukas Lechner    schedule 21.10.2016
comment
почему бы не использовать вместо этого анко: P - person Cuong Vo; 29.10.2018
comment
KotterKnife заменяет масло? это лучше я имею в виду - person shareef; 04.01.2019
comment
Библиотека устарела с предупреждением - This was a terrible idea because it allocates an object for every view reference. Do not use, and do not use anything like it. Use view binding instead. - person anotherdave; 23.04.2020

В моем случае я неправильно собирал ButterKnife. Убедитесь, что вы импортируете его компилятор в build.gradle вашего модуля:

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

обсуждение в ветке примеров Jetbrain пролило для меня больше света на эту проблему.

Другая проблема заключается в том, что вы могли обращаться к представлениям до создания контейнера. Вот связанный вопрос, обсуждение там специфично для синтетических свойств kotlinx, но та же логика должен применяться к привязке вида Butterknife

person kip2    schedule 18.03.2018

для меня эта ошибка возникает, когда include один и тот же макет несколько раз

Например

 <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        >

        <include layout="@layout/chart_bar_layout" />

 </LinearLayout>
 ...
 <include layout="@layout/chart_bar_layout" /> 

Так что найдите и удалите эту строку, чтобы приложение работало нормально

person Radesh    schedule 21.10.2020

Есть небольшая хитрость, которую вы можете попробовать, используя Platform.runLater

 init {
        Platform.runLater {
        ....
        }
 }
person Adel    schedule 23.08.2020

Ваш блок инициализатора не вызывается. Он вызывается только при вызове вашего основного конструктора. В вашем случае вторичный конструктор используется, когда объекты представления создаются из макетов xml.

Измените блок init{...} на fun init(){...} и назовите его первым оператором в каждом конструкторе.

Вы забыли добавить конструктор

constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

=> добавьте его и вызовите в нем init()

person Lukas Lechner    schedule 21.10.2016
comment
когда я использую this (ctx), он говорит, что выражение this типа MenuItemView не может быть вызвано как функция. Функция invoke () не найдена - person Jemo Mgebrishvili; 21.10.2016
comment
та же проблема, возможно, это ошибка, есть также открытая проблема в простом проекте Jetbrains github.com/ JetBrains / kotlin-examples / issues - person Jemo Mgebrishvili; 21.10.2016
comment
вторичные конструкторы вызывают первичный конструктор и выполняются блоки инициализации. Некоторые методы создания экземпляра класса могут не вызывать никаких конструкторов (они существуют). - person Jayson Minard; 23.05.2017