尝试访问Kotlin片段中的视图时出现NullPointerException

Sol*_*dak 210 android kotlin kotlin-android-extensions

如何使用Kotlin Android扩展程序Fragment?如果我在里面使用它们onCreateView(),我得到这个NullPointerException例外:

引起:java.lang.NullPointerException:尝试在空对象引用上调用虚方法'android.view.View android.view.View.findViewById(int)'

这是片段代码:

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
    }
}
`
Run Code Online (Sandbox Code Playgroud)

Ego*_*uba 404

Kotlin合成属性不是神奇的,并且以非常简单的方式工作.当您访问时btn_K,它需要getView().findViewById(R.id.btn_K).

问题是您过早访问它.getView()返回nullonCreateView.尝试在onViewCreated方法中执行此操作:

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

  • 我总是在 onViewCreated 中使用它,但仍然在某些设备上(我从 Crashlytics 得到了报告)它得到了“不能为空”的异常。景色就在那里。我膨胀了正确的布局,它适用于我的设备。奇怪的是不能在随机设备上工作。 (9认同)
  • 你也可以像`rootView.btn_K`那样访问它,如果你有一个视图(而不仅仅是片段,这可以在任何地方完成) (7认同)
  • 有效!!谢谢.快速提醒以备将来参考.我有另一个例外,我挖得更深一些,结果是Null Reference Exception来自异步回调到UI线程,它会尝试访问合成属性,但当时它已经为null.确保使用_Safe Call_运算符(?.)或其他一些空安全运算符.它还有助于保持视图的类引用,而不依赖于`onViewCreated()`之外的合成属性 (2认同)
  • 但有一个问题 - 它为Activity和Fragment生成不同的代码?如果我们使用另一个不包含`getView()`的结构,或者它不能调用`findViewById()`,有没有办法解决它?例如,教它哪个函数将返回我的布局? (2认同)

小智 7

btn_K这么快就调用它,因为那时它返回一个null并且给你Null Pointer Exception.

您可以通过此合成插件在Fragment生命周期onActivityCreated()之后调用的方法中使用这些视图onCreateView().

onActivityCreated()
{
        super.onActivityCreated(savedInstanceState)
        btn_K.setOnClickListener{}
}
Run Code Online (Sandbox Code Playgroud)


onm*_*133 7

Kotlin Android Extensions 插件生成的合成属性需要事先设置一个viewfor Fragment/Activity

在您的情况下, for Fragment,您需要使用view.btn_KinonViewCreated

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
}
Run Code Online (Sandbox Code Playgroud)

或者更好的是,您应该只访问合成属性 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`
}
Run Code Online (Sandbox Code Playgroud)

请注意savedInstanceState参数应该可以为空Bundle?,并检查导入合成属性

一次性导入特定布局的所有小部件属性很方便:

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

因此,如果布局文件名是 activity_main.xml,我们将导入 kotlinx.android.synthetic.main.activity_main.*.

如果我们想调用 View 上的合成属性,我们还应该导入 kotlinx.android.synthetic.main.activity_main.view.*.


Rhu*_*fer 5

您唯一需要做的是:

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
}
Run Code Online (Sandbox Code Playgroud)