android-fragments 无法从RecyclerView适配器启动片段

zazmityj  于 2022-11-13  发布在  Android
关注(0)|答案(1)|浏览(263)

RecyclerView适配器中有一个NameListHolder类代码

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.setOnClickListener中,应该触发该片段,但是当我单击列表项时,抛出了NullPointerException

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指向DescriptionFragment片段中的字符串val position: Int = bundle!!.getInt("position", 0)
NameListAdapter.kt:49指向NameListHolder内部的val fragment = DescriptionFragment()线
Unknown Source:0Unknown Source:4总是指向第0行和第4行,无论那里有什么(在有newInstance()导入之前)
整个数据链:
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>
gtlvzcf8

gtlvzcf81#

您正在此行中创建新片段

val fragment = DescriptionFragment()

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

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

尚未设置,您将在Fragment创建后的下一行中执行此操作。但您将在最开始时强制从bundle(!!)读取,此时它是null,因此会出现NullPointerException
您的方法是错误的,当您确信Fragment已创建、已设置(例如,Bundle参数集)、已添加到布局并正在运行(因为它正在调用生命周期方法)时,您应该读取某些生命周期方法(如onCreateonCreateView)中的参数

相关问题