Исключение NullPointerException при попытке доступа к представлениям во фрагменте Kotlin


как использовать расширения Kotlin Android с Fragments? Если я использую их внутри onCreateView(), Я понял это NullPointerException исключения:

вызвано: java.ленг.NullPointerException: попытка вызвать виртуальный метод 'для Андроид.вид.Вид на Андроид.вид.Вид.findViewById (int)' на a нулевая ссылка на объект

вот фрагмент кода:

package com.obaied.testrun.Fragment

import android.os.Bundle
import android.support.v4.app.Fragment
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.obaied.acaan.R
import kotlinx.android.synthetic.main.fragment_card_selector.*

public class CardSelectorFragment : Fragment() {
    val TAG = javaClass.canonicalName

    companion object {
        fun newInstance(): CardSelectorFragment {
            return CardSelectorFragment()
        }
    }

    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        var rootView = inflater?.inflate(R.layout.fragment_card_selector, container, false)
        btn_K.setOnClickListener { Log.d(TAG, "onViewCreated(): hello world"); }

        return rootView
    }
}
`
7 130

7 ответов:

синтетические свойства Котлина не волшебны и работают очень простым способом. Когда вы получаете доступ btn_K, он требует getView().findViewById(R.id.btn_K).

проблема в том, что вы получаете доступ к нему слишком рано. getView() возвращает null на onCreateView. Попробуйте сделать это в onViewCreated способ:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    btn_K.setOnClickListener { Log.d(TAG, "onViewCreated(): hello world"); }
}

вы называете это btn_K слишком рано, как в то время он возвращает null и дает вам исключение нулевого указателя.

вы можете использовать эти представления с помощью этого синтетического плагина в onActivityCreated() метод, который вызывается сразу после onCreateView() жизненный цикл фрагмента.

onActivityCreated()
{
        super.onActivityCreated(savedInstanceState)
        btn_K.setOnClickListener{}
}

во фрагментах, пожалуйста, напишите свой код в onActivityCreated: -

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        super.onCreateView(inflater, container, savedInstanceState)
        return inflater.inflate(R.layout.login_activity, container, false)

    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        callbackManager = CallbackManager.Factory.create()
        initialization()
        onClickLogin()
        onClickForgot()
        onClickSocailLogIn()

  }

единственное, что вам нужно сделать, это:

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    var rootView = inflater?.inflate(R.layout.fragment_card_selector, container, false)
    rootView.btn_K.setOnClickListener { Log.d(TAG, "onViewCreated(): hello world"); }

    return rootView
}

синтетические свойства, созданные Kotlin Android Extensions plugin нужен view на Fragment/Activity должен быть установлен, прежде чем руки.

в вашем случае, для Fragment, вы должны использовать view.btn_K на onViewCreated

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    super.onCreateView(inflater, container, savedInstanceState)
    val view = inflater.inflate(R.layout.fragment_card_selector, container, false)
    view.btn_K.setOnClickListener{} // access with `view`
    return view
}

или лучше, вы должны получить доступ только к синтетическим свойствам в onViewCreated

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    super.onCreateView(inflater, container, savedInstanceState)
    return inflater.inflate(R.layout.fragment_card_selector, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    btn_K.setOnClickListener{} // access without `view`
}

Пожалуйста, обратите внимание, что savedInstanceState параметр должен быть nullable Bundle?, а также чек импорт синтетических свойства

удобно импортировать все свойства виджета для конкретного макета одним махом:

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

таким образом, если имя файла макета activity_main.xml, мы бы импортировали kotlinx.android.synthetic.main.activity_main.*.

если мы хотим вызвать синтетические свойства на вид, мы должны также импорт kotlinx.android.synthetic.main.activity_main.view.*.

Если вы написали, казалось бы, правильный код, но все равно получите ошибку; Чистый, перестроить и перезапустить Android Studio работал для меня..

class CardSelectorFragment : Fragment() {


val TAG = javaClass.canonicalName

companion object {
    fun newInstance(): CardSelectorFragment {
        return CardSelectorFragment()
    }
}

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    var rootView = inflater?.inflate(R.layout.fragment_card_selector, container, false)

    rootView?.findViewById<TextView>(R.id.mTextView)?.setOnClickListener{
        Log.d(TAG, "onViewCreated(): hello world");
    }
    //btn_K.setOnClickListener { Log.d(TAG, "onViewCreated(): hello world"); }
    return rootView
}

}

* * здесь вы используете btn_K. setOnClickListener перед поиском -Вы должны найти xml-форму элемента для вашего кода java/kotlin с помощью findViewById, а затем только вы можете выполнить операцию над этим представлением или элементом.

- так вот почему нулевой указатель execption вы получили

**