-2

So I have recycler view with the data from public API. I have activity_main.xml just for the FrameLayout, fragment_main.xml for the recyclerView and user_row.xml for the user row in the recycler view. When I start the app it does not even load up and shuts down with error saying:

" java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference "

This is the MainActivity. Its just for the fragment call

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()
    }

as you can see the error is caused by the Button click. The button is for calling another fragment

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()
    }

I have tried doing

val btn: Button = detailBtn!!

but the error changed to the NullPointerException

Its maybe because the detailBtn is in another layout, but I am not sure and I don't know how I would fix it.

Here`s the main_activity.xml layout

<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>

Here's the fragment_main.xml layout

<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"
/>

and here's the user_row layout with the Button and with the idTextView (idTV)

<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>
tynn
  • 38,113
  • 8
  • 108
  • 143
Kry100F
  • 1
  • 1
  • 5

2 Answers2

0

Please add full code before asking the question. I'd be interested to see where you made findViewById(R.id.buttonId) call in your fragment. NullPointerException generally occurs in code if forget to make findViewById call on the view. It also occurs if you made the findViewById call, but the view you're trying to find is in different layout/view hierarcy. I'd be able to help you if you post the full code.(I do not have commenting privileges as of yet)

Vedprakash Wagh
  • 3,595
  • 3
  • 12
  • 33
0

Your detailBtn is part of a RecyclerView cell. Therefore it's not yet attached to the view hierarchy and might not even be unique in it.

You'd have to define the OnClickListener with your RecyclerView.Adapter pass the information to the fragment.

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
    }
}
tynn
  • 38,113
  • 8
  • 108
  • 143
  • Do you mean passing the information in the NewInstance when calling it in the MainActivity? – Kry100F May 09 '19 at 08:39
  • I added a basic example. You have to handle it within the fragment and the adapter. The activity doesn't play any part in it. – tynn May 09 '19 at 08:55