У меня есть небольшой проект в качестве примера:
// MainActivity.kt
package com.example.scratch
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
<!-- layout/activity_main.xml -->
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.scratch.CustomViewWithContent
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
// CustomViewWithContainer.kt
package com.example.scratch
import android.content.Context
import android.util.AttributeSet
import android.view.Gravity
import android.view.View
import android.widget.FrameLayout
import androidx.constraintlayout.widget.ConstraintLayout
open class CustomViewWithContainer : ConstraintLayout {
private val contentContainer by lazy {
findViewById<FrameLayout>(R.id.content_container)
}
constructor(context: Context?) : super(context) {
commonInit(context)
}
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
commonInit(context)
}
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
) {
commonInit(context)
}
protected open fun commonInit(context: Context?) {
if (context == null) {
return
}
inflate(context, R.layout.custom_view_with_container, this)
if (isInEditMode) {
return
}
}
protected fun setContent(contentView: View) {
contentContainer.removeAllViews()
contentContainer.addView(contentView)
(contentView.layoutParams as FrameLayout.LayoutParams).gravity = Gravity.CENTER
}
}
<!-- layout/custom_view_content.xml -->
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is a text view" />
</FrameLayout>
// CustomViewWithContent.kt
package com.example.scratch
import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.widget.TextView
class CustomViewWithContent : CustomViewWithContainer {
private lateinit var contentView: View
private val textView by lazy {
contentView.findViewById<TextView>(R.id.text_view)
}
constructor(context: Context?) : super(context)
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
override fun commonInit(context: Context?) {
super.commonInit(context)
if (context == null) {
return
}
contentView = inflate(context, R.layout.custom_view_content, null)
if (isInEditMode) {
return
}
setContent(contentView)
Log.d(
CustomViewWithContent::class.java.simpleName,
"TextView id: ${textView.id}"
)
}
}
<!-- layout/custom_view_with_container -->
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
<FrameLayout
android:id="@+id/content_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</merge>
Но когда я запускаю его, он падает, отображая следующееlog: ![log of the crash](https://i.stack.imgur.com/zQ5xm.png)
И я не знаю, почему он падает. Идентификатор представления, которое я получаю, в точности равен тому, который можно найти в макете .xml
.
Мне бы хотелось узнать причину, по которой ленивый возвращает null
вместосмотреть сам, потому что это не имеет смысла: /
![enter image description here](https://i.stack.imgur.com/RZxW7.gif)
Через этот GIF, мы можем видеть, что:
textView
(то есть lazy val
) считается нулевым; notNullTextView
не равно нулю и выполняет тот же код, найденный внутри text view
lazyБлок инициализации val; - , выполняющий тот же код инициализации
textView
в Watches IDE, также возвращает ноль.