There is a code for the NameListHolder class located in the RecyclerView adapter
class NameListHolder(val binding: NameListItemBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(paginationLocalModel: PaginationLocalModel, position: Int, context: NameListFragment){
binding.name.text = paginationLocalModel.name
itemView.setOnClickListener{
val fragment = DescriptionFragment()
val bundle = Bundle()
bundle.putInt("position", position)
fragment.setArguments(bundle)
val activity=context.context as AppCompatActivity
activity.supportFragmentManager
.beginTransaction()
.replace(R.id.rd_fragment, fragment)
.commitNow()
Log.d("OnClick", "произошло нажатие по позиции $position")
}
}
}
Inside itemView.setOnClickListener the fragment should fire, but when I click on the list item, a NullPointerException is thrown:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.sem.receivedata, PID: 5484
java.lang.NullPointerException
at com.sem.receivedata.presentation.DescriptionFragment.<init>(DescriptionFragment.kt:22)
at com.sem.receivedata.presentation.adapters.NameListAdapter$NameListHolder.bind$lambda-0(NameListAdapter.kt:49)
at com.sem.receivedata.presentation.adapters.NameListAdapter$NameListHolder.$r8$lambda$FuXGFWDKhm2ZD3YhtF7Xh98aUvc(Unknown Source:0)
at com.sem.receivedata.presentation.adapters.NameListAdapter$NameListHolder$$ExternalSyntheticLambda0.onClick(Unknown Source:4)
DescriptionFragment.kt:22 points to the string val position: Int = bundle!!.getInt("position", 0) inside the DescriptionFragment fragment
NameListAdapter.kt:49 points to the line val fragment = DescriptionFragment() inside the NameListHolder
Unknown Source:0 and Unknown Source:4 always point to line 0 and 4, no matter what is there (before there were newInstance() imports)
The whole data chain:
NameListFragment:
class NameListFragment : Fragment() {
...
private fun initRecyclerExchangeRate(){
binding?.listNameRV?.layoutManager =
LinearLayoutManager(context)
nameListAdapter = NameListAdapter(this)
binding?.listNameRV?.adapter = nameListAdapter
}
...
}
NameListAdapter:
class NameListAdapter(var context: NameListFragment
) : RecyclerView.Adapter<NameListAdapter.NameListHolder>() {
...
override fun onBindViewHolder(holder: NameListHolder, position: Int) {
holder.bind(pagination[position], position, context)
}
...
class NameListHolder(val binding: NameListItemBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(paginationLocalModel: PaginationLocalModel, position: Int, context: NameListFragment){
binding.name.text = paginationLocalModel.name
itemView.setOnClickListener{
val fragment = DescriptionFragment()
val bundle = Bundle()
bundle.putInt("position", position)
fragment.setArguments(bundle)
val activity=context.context as AppCompatActivity
activity.supportFragmentManager
.beginTransaction()
.replace(R.id.rd_fragment, fragment)
.commitNow()
Log.d("OnClick", "произошло нажатие по позиции $position")
}
}
}
...
}
DescriptionFragment:
class DescriptionFragment : Fragment() {
...
val bundle: Bundle? = this.getArguments();
val position: Int = bundle!!.getInt("position", 0)
...
}
The launch of the first fragment from the Activity is done inside the markup:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".presentation.MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@ id/framelayout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="@ id/rd_fragment"
android:name="com.sem.receivedata.presentation.NameListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
CodePudding user response:
you are creating new fragment in this line
val fragment = DescriptionFragment()
so it gets created and at start it tries to parse bundle
val bundle: Bundle? = this.getArguments();
val position: Int = bundle!!.getInt("position", 0)
which isn't set yet, you are doing this in next lines after Fragment creation. but you are forcing to read from bundle (!!) at very beginning, it's null at this moment, so NullPointerException occurs
your aproach is just wrong, you should read arguments in some lifecycle method like onCreate or onCreateView, when you are shure that Fragment is created, is set up (e.g. Bundle arguments set), is added to layout and running (as it is calling lifecycle methods)
