【问题标题】:Button onClick doesn't work in Fragment, throws "null object reference" error even after declaring it [duplicate]按钮 onClick 在 Fragment 中不起作用,即使在声明它之后也会引发“空对象引用”错误 [重复]
【发布时间】:2019-05-09 08:10:58
【问题描述】:

所以我有来自公共 API 的数据的回收站视图。我的activity_main.xml 仅用于FrameLayout,fragment_main.xml 用于recyclerView,而user_row.xml 用于recycler 视图中的用户行。当我启动应用程序时,它甚至没有加载并关闭并显示错误消息:

“java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)'”

这是 MainActivity。它只是用于片段调用

class MainActivity : AppCompatActivity(), BlankFragment.OnFragmentInteractionListener {
    lateinit var blankFragment: BlankFragment

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        blankFragment = BlankFragment.newInstance()

        supportFragmentManager
            .beginTransaction()
            .add(R.id.fragmentContainer,blankFragment)
            .addToBackStack(blankFragment.toString())
            .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
            .commit()
    }

如您所见,错误是由按钮单击引起的。该按钮用于调用另一个片段

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    detailBtn.setOnClickListener {
        detailFragment = DetailFragment.newInstance(idTV.text.toString().toInt())
        fragmentManager!!.beginTransaction()
            .replace(R.id.fragmentContainer, detailFragment)
            .addToBackStack(BlankFragment.toString())
            .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
            .commit()
    }

我试过了

val btn: Button = detailBtn!!

但是错误变成了 NullPointerException

这可能是因为 detailBtn 在另一个布局中,但我不确定,也不知道如何修复它。

这是 main_activity.xml 布局

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width="match_parent"
             android:id="@+id/fragmentContainer"
             android:layout_height="match_parent">
</FrameLayout>

这是 fragment_main.xml 布局

<android.support.v7.widget.RecyclerView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
/>

这是带有 ButtonidTextView (idTV)

的 user_row 布局
<android.support.constraint.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:onClick="itemClicked"
        android:layout_height="wrap_content"
        xmlns:app="http://schemas.android.com/apk/res-auto">


    <TextView
            android:layout_marginLeft="16dp"
            android:id="@+id/idTV"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/usernameTV"
            tools:text="ID"
            android:textSize="25sp"
            android:textColor="#D32F2F"
            android:padding="8dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

    <TextView
            android:layout_marginLeft="16dp"
            android:id="@+id/usernameTV"
            app:layout_constraintStart_toEndOf="@+id/idTV"
            app:layout_constraintTop_toTopOf="parent"
            tools:text="Userame"
            android:textSize="25sp"
            android:textColor="#000"
            android:padding="8dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

    <Button app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            android:text="+"
            android:textSize="35sp"
            android:layout_marginRight="16dp"
            android:id="@+id/detailBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#E91E63"/>

    <View
            app:layout_constraintTop_toBottomOf="@id/usernameTV"
            android:layout_width="match_parent"
            android:layout_height="3px"
            android:layout_marginLeft="5dp"
            android:layout_marginRight="5dp"
            android:background="#000"/>

</android.support.constraint.ConstraintLayout>

【问题讨论】:

  • 您从未引用过该按钮;使用View.findViewById()
  • @SusmitAgrawal 是 kotlin,不需要 findviewbyId
  • 在 Kotlin 中不需要 findviewbyid

标签: android android-fragments kotlin android-recyclerview


【解决方案1】:

请在提问前添加完整代码。我很想知道您在片段中的findViewById(R.id.buttonId) 调用位置。如果忘记在视图上调用findViewByIdNullPointerException 通常出现在代码中。如果您进行了 findViewById 调用,也会发生这种情况,但您尝试查找的视图位于不同的布局/视图层次结构中。如果您发布完整的代码,我可以为您提供帮助。(我还没有评论权限)

【讨论】:

  • 它是 kotlin,不需要通过 id 查找视图
  • 在 Kotlin 中不需要 findviewbyid
  • 感谢您添加!那我需要学习Kotlin。此外,这肯定是另一个问题,从另一个布局/视图层次结构中引用一个视图。
【解决方案2】:

您的detailBtnRecyclerView 单元格的一部分。因此它还没有附加到视图层次结构中,甚至可能不是唯一的。

您必须使用您的RecyclerView.Adapter 定义OnClickListener,将信息传递给片段。

adapter.setOnClickListener { idTV ->
    detailFragment = DetailFragment.newInstance(idTV.text.toString().toInt())
    fragmentManager!!.beginTransaction()
        .replace(R.id.fragmentContainer, detailFragment)
        .addToBackStack(BlankFragment.toString())
        .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
        .commit()
}

class Adapter : RecyclerView.Adapter() {
    private lateinit var listener: (TextView) -> Unit
    fun setOnClickListener(listener: (TextView) -> Unit) {
        this.listener = listener
    }

    override fun onCreateViewHolder(parent: ViewGroup, type: Int): ViewHolder {
        val viewHolder = ...
        viewHolder.itemView.run {
            detailBtn.setOnClickListener {
                listener(idTV)
            }
        }
        return viewHolder
    }
}

【讨论】:

  • 你的意思是在MainActivity中调用的时候传递NewInstance中的信息吗?
  • 我添加了一个基本示例。您必须在片段和适配器中处理它。该活动不参与其中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-18
  • 1970-01-01
  • 1970-01-01
  • 2017-02-06
  • 2017-02-19
  • 1970-01-01
相关资源
最近更新 更多