无法从 RecyclerView 适配器启动 Fragment

Can't launch Fragment from RecyclerView adapter

提问人:Иван Петров 提问时间:9/9/2022 更新时间:9/9/2022 访问量:113

问:

NameListHolder 类的代码位于 RecyclerView 适配器中

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

    }

}

在片段内部应该触发,但是当我单击列表项时,会抛出一个:itemView.setOnClickListenerNullPointerException

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指向片段内的字符串val position: Int = bundle!!.getInt("position", 0)DescriptionFragment

NameListAdapter.kt:49指向val fragment = DescriptionFragment()NameListHolder

Unknown Source:0并始终指向第 0 行和第 4 行,无论那里有什么(在有导入之前)Unknown Source:4newInstance()

整个数据链:

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)

...

}

Activity 中第一个片段的启动是在标记中完成的:

<?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>
android kotlin android-fragments android-recyclerview nullpointerexception

评论


答:

0赞 snachmsm 9/9/2022 #1

您正在此行中创建新片段

val fragment = DescriptionFragment()

因此,它被创建并在开始时尝试解析捆绑包

val bundle: Bundle? = this.getArguments();
val position: Int = bundle!!.getInt("position", 0)

尚未设置,您将在创建后的下一行中执行此操作。但是你一开始就强制从bundle()中读取,就在此时此刻,所以发生了Fragment!!nullNullPointerException

你的 aproach 是错误的,你应该阅读一些生命周期方法中的参数,比如 or ,当你被创建的 Shure 时,被设置(例如 arguments set),被添加到布局和运行中(因为它正在调用生命周期方法)onCreateonCreateViewFragmentBundle