Intereting Posts
Параллельная анимация в Imageview Почему некоторые Android-телефоны заставляют наше приложение бросать java.lang.UnsatisfiedLinkError? Пользовательские действия с использованием неявных намерений между приложениями Как получить RegistrationID с помощью GCM в android Андроидный запрос пользователя с помощью диалога В чем разница между Robolectric.setupActivity () и Robolectric.buildActivity ()? Как создать точку доступа программно Получение android.content.res.Resources $ NotFoundException: исключение, даже если ресурс присутствует в android Изменить направление строки действия справа налево Родной сбой в /system/lib/libwebviewchromium.so на Android-андроиде 4.4 FragmentTransaction .attach и .detach для вкладок Actionbar Assert ImageView был загружен конкретным идентификатором ресурса ресурса Кнопка – изменение цвета фона при нажатии Android Nested Fragments Issue "java.lang.IllegalStateException: активность была уничтожена" Как получить количество предметов в прядильщике?

Kotlin lateinit свойства, опасность NPE?

Я использую свойства lateinit, чтобы избежать непрерывной проверки нуля с помощью? оператор. У меня много свойств вида, которые назначаются впервые в функции getViews (). Если этой функции не было, мое приложение вылетает с NPE, из кода Kotlin.

По-моему, свойства lateinit в основном разрушают хорошие нулевые функции безопасности языка. Я знаю, что они введены в M13 из-за лучшей поддержки рамок, но стоит ли это?

Или я чего-то не хватает?

Вот код:

package com.attilapalfi.exceptional.ui import android.os.Bundle import android.support.v7.app.AppCompatActivity import android.view.View import android.widget.Button import android.widget.ImageView import android.widget.TextView import com.attilapalfi.exceptional.R import com.attilapalfi.exceptional.dependency_injection.Injector import com.attilapalfi.exceptional.model.Exception import com.attilapalfi.exceptional.model.ExceptionType import com.attilapalfi.exceptional.model.Friend import com.attilapalfi.exceptional.persistence.* import com.attilapalfi.exceptional.rest.ExceptionRestConnector import com.attilapalfi.exceptional.ui.helpers.ViewHelper import com.attilapalfi.exceptional.ui.question_views.QuestionYesNoClickListener import com.google.android.gms.maps.MapView import java.math.BigInteger import javax.inject.Inject public class ShowNotificationActivity : AppCompatActivity(), QuestionChangeListener { @Inject lateinit val exceptionTypeStore: ExceptionTypeStore @Inject lateinit val friendStore: FriendStore @Inject lateinit val imageCache: ImageCache @Inject lateinit val metadataStore: MetadataStore @Inject lateinit val viewHelper: ViewHelper @Inject lateinit val exceptionInstanceStore: ExceptionInstanceStore @Inject lateinit val exceptionRestConnector: ExceptionRestConnector @Inject lateinit val questionStore: QuestionStore private lateinit var sender: Friend private lateinit var exception: Exception private lateinit var exceptionType: ExceptionType private lateinit var exceptionNameView: TextView private lateinit var exceptionDescView: TextView private lateinit var senderImageView: ImageView private lateinit var senderNameView: TextView private lateinit var sendDateView: TextView private lateinit var mapView: MapView private lateinit var questionText: TextView private lateinit var noButton: Button private lateinit var yesButton: Button override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_show_notification) Injector.INSTANCE.applicationComponent.inject(this) questionStore.addChangeListener(this) getModelFromBundle() getViews() loadViewsWithData() } override fun onDestroy() { super.onDestroy() questionStore.removeChangeListener(this) } private fun getModelFromBundle() { val bundle = intent.extras val instanceId = BigInteger(bundle.getString("instanceId")) exception = exceptionInstanceStore.findById(instanceId) sender = friendStore.findById(exception.fromWho) exceptionType = exceptionTypeStore.findById(exception.exceptionTypeId) } private fun getViews() { exceptionNameView = findViewById(R.id.notif_full_exc_name) as TextView exceptionDescView = findViewById(R.id.notif_exc_desc) as TextView senderImageView = findViewById(R.id.notif_sender_image) as ImageView senderNameView = findViewById(R.id.notif_sender_name) as TextView sendDateView = findViewById(R.id.notif_sent_date) as TextView mapView = findViewById(R.id.notif_map) as MapView questionText = findViewById(R.id.notif_question_text) as TextView noButton = findViewById(R.id.notif_question_no) as Button yesButton = findViewById(R.id.notif_question_yes) as Button } private fun loadViewsWithData() { exceptionNameView.text = exceptionType.prefix + "\n" + exceptionType.shortName exceptionDescView.text = exceptionType.description imageCache.setImageToView(sender, senderImageView) senderNameView.text = viewHelper.getNameAndCity(exception, sender) sendDateView.text = exception.date.toString() loadQuestionToViews() } private fun loadQuestionToViews() { if (exception.question.hasQuestion) { showQuestionViews() } else { hideQuestionViews() } } private fun showQuestionViews() { questionText.text = exception.question.text val listener = QuestionYesNoClickListener(exception, exceptionRestConnector, noButton, yesButton) noButton.setOnClickListener(listener) yesButton.setOnClickListener(listener) } private fun hideQuestionViews() { questionText.visibility = View.INVISIBLE noButton.visibility = View.INVISIBLE yesButton.visibility = View.INVISIBLE } override fun onQuestionsChanged() { onBackPressed() } } 

Solutions Collecting From Web of "Kotlin lateinit свойства, опасность NPE?"

Та же самая основная особенность lateinit была фактически возможна с Delegates.notNull до M13.

Существуют и другие функции, которые также позволяют обойти применение правил недействительности. Привет! Оператор преобразует значение с нулевым значением в ненулевое значение.

Дело не в том, чтобы строго требовать ограничения на неопределенность, а в том, чтобы сделать допустимость нулевой черты очень явной частью языка. Каждый раз, когда вы используете lateinit или !! Вы принимаете осознанное решение оставить безопасность ограничений неопределенности, надеюсь, не без оснований.

Как правило, лучше избегать lateinit , !! , И даже ? (Обнулять) как можно больше.

Много времени вы можете использовать ленивого делегата, чтобы избежать lateinit, который может держать вас в сфере ненулевых vals (M14 теперь запрещает использование vals с lateinit ).

Код, к которому вы привязаны, включает множество просмотров. Вы можете сохранить их как ненулевые vals, сделав что-то вроде этого:

 private val mapView: MapView by lazy { findViewById(R.id.notif_map) as MapView } 

Это будет инициализировать значение при первом использовании mapView и использовать ранее инициализированное значение после этого. Предостережение заключается в том, что это может сломаться, если вы попытались использовать mapView перед вызовом setContentView . Тем не менее, это не похоже на эту сделку, и вы получили то преимущество, что ваша инициализация находится рядом с вашей декларацией.

Это то, что делает библиотека kotterknife для достижения инъекции зрения.

Лётная делегация Котлина будет работать во многих случаях, хотя у вас возникнут проблемы при перезагрузке фрагментов, которые были сохранены в FragmentManager. Когда система Android перестроит фрагмент, она фактически воссоздает представление, вызывающее view?.findViewById(R.id.notif_map) чтобы фактически вернуть недопустимый вид.

В этих случаях вам придется использовать свойство только для чтения:

 private val mapView: MapView get() = view?.findViewById(R.id.notif_map) as MapView