Свойство 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()
в нем