首页 > 解决方案 > Kotlin:将数据传递给片段

问题描述

我有一个包含 RecyclerView 的片段。通过这个 RecyclerView,我希望单击任何视图以打开另一个片段(其中包含不同的回收器视图)。RecyclerView 的每个视图都包含一个图片 URL 和一些文本。我希望将这两个都传递给第二个片段,以便我可以在 ImageView 和 TextView 中使用它。

我已经设法用 RecyclerView 适配器打开了第二个片段,但是我很难将数据从 RecyclerView 传递到我的第二个片段。

这是我的代码:

RecyclerView 适配器

class ManuAdapter(private val manu: List<Manufacturers>) :
    RecyclerView.Adapter<ManuAdapter.ViewHolder>() {


    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val mpos = manu[position]
        Picasso.get().load(mpos.bgphoto).into(holder.image)
        holder.manufacturer.text = mpos.manufacturer

        holder.itemView.setOnClickListener {

            val activity = it.context as AppCompatActivity

            CarListFragment.newInstance(mpos.manufacturer)
            Timber.e("The string is: ${mpos.manufacturer}")

            activity.supportFragmentManager.beginTransaction()
                .replace(R.id.frameLayout, CarListFragment())
                .addToBackStack(null)
                .commit()
        }

    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.manu_row, parent, false)

        return ViewHolder(view)
    }


    override fun getItemCount() = manu.size

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val image: ImageView = itemView.manu_photo
        val manufacturer: TextView = itemView.manufacturer
    }
}

我试图向其发送信息的片段

class CarListFragment : Fragment() {

    companion object {
        private const val ARG_TEXT = "myFragment_text"

        fun newInstance(text: String): CarListFragment {
            val args = Bundle()
            args.putString(ARG_TEXT, text)
            val fragment = CarListFragment()
            fragment.arguments = args
            return fragment
        }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {

        val root = inflater.inflate(R.layout.fragment_car_list, container, false)


        //RecyclerView in the second fragment
        val carsRepository = CarsRepository().getAllCars()
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe({
            root.recycler_view.apply {
                layoutManager = LinearLayoutManager(activity)
                adapter = CarsAdapter(it)
                root.loadingicon.visibility = View.GONE
                root.loadingtext.visibility = View.GONE
            }
        }, {
        })


        val index = arguments?.getString(ARG_TEXT,"")
        Timber.e("index is: $index")
        root?.manu_name?.text = index

        return root
    }
}

单击 RecyclerView 中的视图后,我的 Adapter 类中的日志语句显示正确的 String 被放入 newInstance 构造函数中。但是,在我的第二个片段中,我的索引日志语句显示它为空。

标签: androidkotlinandroid-fragmentsandroid-recyclerview

解决方案


好的,我设法弄清楚如何将我的数据获取到我的第二个片段。我找到的解决方案并不太复杂,所以我认为这会帮助像我一样刚进入编码/kotlin 的人。这可能不是最有效的方法,但对我来说已经足够了。

基本上,我添加了一个接口和一个侦听器,用于将单击recyclerview 的信息传递到片段#1,片段#1 将recyclerview 保存到片段#2。我传达的三个数据是列表的位置和两个字符串(其中一个是图像 URL)。

我用来开发代码的两个来源是一个视频,它介绍了如何通过 onClickListener 从 RecyclerView 获取数据到我的片段 #1 (MainFragment) 和一个教程,展示了如何将该数据传达给片段 #2 (CarListFragment) .

首先,我创建了界面: 我把它放在它自己的文件中只是为了让事情更整洁

package com.myname.mypackage
    
interface Communicator {
    fun passData(position: Int, name: String, image: String)
}

在我的 RecyclerView 适配器中:

  • 从我的 onBindViewHolder 中删除了 OnClickListener,因为这会减慢应用程序的速度(这是我最初在问题中所做的)
  • 添加private val listener: Communicator到顶部的适配器构造函数
  • 在我的 ViewHolder 课程中
    • 将类更改为内部类
    • View.OnClickListener在扩展“:”之后添加
    • 为 setOnClickListener 添加了初始化块
    • 添加了override fun onClick(v: View?)

从我链接的视频中遵循了此步骤。

class ManuAdapter(
    private val manu: List<Manufacturers>,
    private val listener: Communicator
    ) :
    RecyclerView.Adapter<ManuAdapter.ViewHolder>() {


    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val currentItem = manu[position]
        Picasso.get().load(currentItem.bgphoto).into(holder.image)
        holder.manu_name.text = currentItem.manufacturer
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.manu_row, parent, false)
        return ViewHolder(view)
    }


    override fun getItemCount() = manu.size

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
        val image: ImageView = itemView.manu_photo
        val manu_name: TextView = itemView.manufacturer

        init {
            itemView.setOnClickListener (this)
        }

        override fun onClick(v: View?) {
            val position = adapterPosition
            val image = manu[adapterPosition].bgphoto
            val name =  manu[adapterPosition].manufacturer
            if (position != RecyclerView.NO_POSITION) {
                listener.passData(position,name, image)
            }
        }
    }
}

在我的片段 #1(它包含 RecyclerView)中:

  • 通过在“:”之后添加 Communicator 在片段中实现 Communicator
  • 在适配器中为侦听器添加上下文line adapter = ManuAdapter(it, this@MainFragment)
  • 在片段#1 类中添加了 passData 函数。

视频中涵盖了创建 onItemClick 函数的所有内容,从这里开始,我将按照教程的其余部分进行操作。

class MainFragment : Fragment(R.layout.fragment_main), Communicator {


    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {

        val root =  inflater.inflate(R.layout.fragment_main, container, false)

        val carsRepository = CarsRepository().getAllManufacturers()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({
                root.recycler_view_main.apply {
                    layoutManager = LinearLayoutManager(activity)
                    adapter = ManuAdapter(it, this@MainFragment)
                    root.loadingicon_main.visibility = View.GONE
                    root.loadingtext_main.visibility = View.GONE
                }
            }, {
            })

        return root
    }

    override fun passData(position: Int, name: String, image: String) {
        val bundle = Bundle()
        bundle.putInt("input_pos", position)
        bundle.putString("input_name", name)
        bundle.putString("input_image", image)

        val transaction = this.parentFragmentManager.beginTransaction()
        val frag2 = CarListFragment()
        frag2.arguments = bundle

        transaction.replace(R.id.frameLayout, frag2)
        transaction.addToBackStack(null)
        transaction.commit()
    }
}

在片段 #2

  • 启动片段后添加三个变量
  • 从 Communicator 界面获取变量
class CarListFragment : Fragment() {

    var inputPos: Int? = null
    var inputName: String = ""
    var inputImage: String = ""

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {

        val root = inflater.inflate(R.layout.fragment_car_list, container, false)

        //code for my fragment in here


        inputPos = arguments?.getInt("input_pos")
        inputName = arguments?.getString("input_name").toString()
        inputImage = arguments?.getString("input_image").toString()
        Picasso.get().load(inputImage).into(root?.manu_pic)
        root?.manu_name?.text = inputName

        return root
    }
}

manu_pic 和 manu_name 只是片段膨胀的 XML 中的 ImageView 和 TextView 的 id。

希望有人觉得这些信息有用。


推荐阅读