Android 尝试访问Kotlin片段中的视图时出现NullPointerException
如何将Kotlin Android扩展与Android 尝试访问Kotlin片段中的视图时出现NullPointerException,android,kotlin,kotlin-android-extensions,Android,Kotlin,Kotlin Android Extensions,如何将Kotlin Android扩展与Fragments一起使用? 如果我在onCreateView()中使用它们,我会得到以下NullPointerException异常: 原因:java.lang.NullPointerException:尝试调用虚拟机 方法“android.view.view android.view.view.findViewById(int)”在 空对象引用 以下是片段代码: package com.obaied.testrun.Fragment import a
Fragment
s一起使用?
如果我在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
}
}
`
Kotlin的合成特性并不是神奇的,而是以一种非常简单的方式工作的。当您访问
btn_K
时,它调用getView().findViewById(R.id.btn_K)
问题是您访问它的时间太短getView()
在onCreateView
中返回null
。尝试在onViewCreated
方法中执行此操作:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
btn_K.setOnClickListener { Log.d(TAG, "onViewCreated(): hello world"); }
}
您调用此
btn_K
太快了,因为此时它返回null,并向您提供null指针异常
在片段生命周期的onCreateView()
之后调用的onActivityCreated()
方法中,您可以通过这个合成插件使用这些视图
onActivityCreated()
{
super.onActivityCreated(savedInstanceState)
btn_K.setOnClickListener{}
}
class CardSelectorFragment:Fragment(){
val TAG=javaClass.canonicalName
伴星{
fun newInstance():CardSelectorFragment{
返回CardSelectorFragment()
}
}
覆盖创建视图(充气机:布局充气机?、容器:视图组?、savedInstanceState:捆绑?):视图{
var rootView=充气机?充气(R.layout.fragment\u card\u选择器,容器,错误)
rootView?.findViewById(R.id.mTextView)?.setOnClickListener{
d(标记“onViewCreated():helloworld”);
}
//btn_K.setOnClickListener{Log.d(标记,“onViewCreated():hello world”);}
返回根视图
}
}
**在查找之前,您正在使用btn_K.setOnClickListener
-您必须使用findviewbyd找到从xml到java/kotlin代码的元素,然后只有您可以对该视图或元素执行操作
-所以这就是为什么你有空指针执行选项
**请在OnActivity中编写代码创建:-
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
}
由生成的合成属性需要一个
视图
,以便片段/活动
事先设置
在您的情况下,对于片段
,您需要在onViewCreated
中使用view.btn_K
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
}
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`
}
或者更好,您应该只在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
}
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
参数应为空Bundle?
,并检查
可以方便地为特定布局导入所有小部件属性
一次性:
导入kotlinx.android.synthetic.main.*
因此,如果布局文件名是activity_main.xml,我们将导入
kotlinx.android.synthetic.main.activity\u main...
如果我们想在视图中调用合成属性,我们还应该
导入kotlinx.android.synthetic.main.activity\u main.view...
在我的情况下,在我遵循评论中的建议之前,一切都不起作用。清理、重建(无需重新启动),重新运行应用程序。我也不需要在activitycreated上使用
,只要onCreateView
就可以了
有一次,我也犯了错误,膨胀了错误的布局,因此显然没有得到预期的控件。无需定义伴生对象,只需通过如下视图调用每个id即可
lateinit var mView: View
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
mView=inflater.inflate(R.layout.product_list,container,false)
mView.addProduct.setOnClickListener {
val intent=Intent(activity,ProductAddActivity::class.java)
startActivity(intent)
} return mView
}
将它添加到@Egor Neliuba的答案中,无论何时调用没有引用的视图,kotlinex都会查找根视图,因为您在片段中,而片段没有getView()
方法。因此,它可能会抛出NullPointerException
有两种方法可以克服这个问题
- 您可以覆盖前面提到的
onViewCreated()
- 或者,如果您想在其他类(比如匿名类)中绑定视图,只需创建如下扩展函数
fun View.bindViews(){…}
第二种方法很有用,当您有一个具有多个行为的片段时。它起作用了!!谢谢只是简单的提醒一下,以备将来参考。我有另一个异常,我深入挖掘了一下,发现Null引用异常来自于对UI线程的异步回调,它将尝试访问合成属性,但当时它已经为Null。确保使用安全呼叫运算符(?)或其他空安全运算符。它也有助于保持视图的类引用,而不依赖于onViewCreated()
之外的合成属性,但有一个问题-它为活动和片段生成不同的代码?如果我们使用另一个不包含getView()
的结构,或者它不能调用findViewById()
,有没有办法解决这个问题?例如,教它哪个函数将返回我的布局?如果你有一个视图(不仅仅是片段,这可以在任何地方完成),你也可以像rootView.btn_K
一样访问它,它可以工作!但是,Kotlin文档中应该更加强调这一点。直到这篇文章我才注意到这个方法。。无论如何谢谢你!我总是在onViewCreated中使用它,但在某些设备上(我从Crashlytics获得了报告),它得到了“不得为null”异常。景色就在那里。我充气正确的布局,它在我的设备上工作。不在随机设备上工作很奇怪。如果您想在onCreateView中工作,btn_K也将是rootView上的一个属性。你可以做rootView.btn_K.setOnClickListener
谢谢@Makotosan你的回答对我有用。清理、重建并重新启动Android studio对我有用me@Otziii这篇文章最早是在2015年写的。第一个答案有259票,被接受。我不认为有必要添加更多的答案。@Solidak我最近遇到了这个问题,尝试了所有的答案,并且是唯一能让它起作用的东西