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

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

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

Ответ 1

Если вы не хотите использовать какие-либо библиотеки третьих сторон, вы можете добавить эти функции расширения (я имею тенденцию иметь 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 и View s. Поэтому внутри вашего класса вместо

@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, когда они не нуждаются в изменении. Как правило, в программировании старайтесь держать вещи как можно более неизменными, вы получите гораздо меньше ошибок.

Ответ 2

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

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

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

Ответ 3

добавить 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"

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

Ответ 4

Я нашел это для меня.

Измените 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)
        //...
    }
}

Enjoy.

Ответ 5

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

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

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

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

Ответ 6

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

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

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

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

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