Как инициализировать виджеты в android с помощью kotlin

Я начал изучать язык kotlin в android и получать проблемы при инициализации моей переменной кнопки, потому что во время определения моей переменной она просит дать некоторое начальное значение, когда я инициализирую нулевое значение и привяжу переменную в функции oncreate, которую она дает

kotlin.KotlinNullPointerException

вот мой код

class AddsFragment : Fragment() { var Add: Button = null!! override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { val Rootview = inflater!!.inflate(R.layout.clubsfragment, null, false) Add = Rootview.findViewById(R.id.add) as Button return Rootview } } 

!! операторы проверяют, является ли приемник null и если он вызывает KotlinNullPointerException . Итак, null!! всегда будет генерировать исключение.

Вы можете добиться того, чего хотите, следующими способами:

  1. Укажите тип свойства Button? , В этом случае при доступе к методам кнопки вам придется использовать либо ? или !! ,

     var add: Button? = null // Initialize it somewhere. add?.setText("Text") // Calls setText if Add != null add!!.setText("Text") // Throws an exception if Add == null 
  2. Сделайте кнопку свойства lateinit .

     lateinit var add: Button 
  3. Сделайте кнопкой свойство notNull delegate.

     var add: Button by Delegates.notNull() 

В последних двух случаях вы не можете проверить, является ли кнопка null . Если вам требуется null сравнение для работы с переменной, используйте первый подход.


Есть еще один подход, который я не буду подробно описывать в этом ответе. Первый использует Kotlin Android Extensions . Это плагин-компилятор, который генерирует синтетические свойства для ваших представлений, поэтому вам не нужно вызывать findViewById() и получать доступ к представлениям с использованием сгенерированных свойств.

Второй способ – создать собственный делегат, который вызовет findViewById() для вас. Это может выглядеть примерно так:

 val add: Button by bindView(R.id.add) 

Вы можете найти пример такого делегата в проекте KotterKnife .

Вы можете использовать Kotlin для написания функции bind хелпера:

 fun <T : View> Activity.bind(@IdRes res : Int) : Lazy<T> { @Suppress("UNCHECKED_CAST") return lazy { findViewById(res) as T } } 

Затем вы можете просто определить свою переменную один раз, используя val (который равен final в Java):

 class MyActivity : AppCompatActivity() { private val button: Button by bind(R.id.button) } 

или

 class MyActivity : AppCompatActivity() { private val button by bind<Button>(R.id.button) } 

Вы можете инициализировать представления в kotlin, используя любой из следующих методов:

1. Неудачные вары

 private var textView: TextView? = null … textView = findViewById(R.id.text_view) as TextView 

2. lateinit

 private lateinit var textView: TextView … textView = findViewById(R.id.text_view) as TextView 

3. Delegates.notNull ()

 private var textView: TextView by Delegates.notNull() … textView = findViewById(R.id.text_view) as TextView 

4. Ленивые свойства

 private val textView: TextView by lazy { findViewById(R.id.text_view) as TextView } 

5. Бутерброд

 @BindView(R2.id.text_view) internal lateinit var textView: TextView 

6. Kotterknife

 private val textView: TextView by bindView(R.id.text_view) 

7. Kotlin Android Extensions

Нет образца кода, просто добавьте правильный импорт и начните использовать синтетические генерируемые свойства, как показано ниже.

 import kotlinx.android.synthetic.main.<layout>.* 

8. привязка данных Android

 binding = FragmentLayoutBinding.inflate(inflater, container, false) ... binding.textView.text = "Hello" 

Вы можете проверить pro / cons каждого метода в разделе «Преимущества / недостатки» стратегии просмотра Android