通过适配器在 Kotlin Android 中的 Fragment 之间传递数据

3

我对编程很新,大约1个月。如果此问题已在其他地方得到解答,那么请原谅,但我已花费数小时查看其他类似的问题,但仍无法得出正确的答案。 问题是:我想传递从片段1(MainFragment)获取的位置点击数据到片段2(MapsFragment),以加载相应的地图。这通过adapter onclick方法进行,因为我想在MainFragment上使用RecyclerView。项目可建立,但是当我在recyclerview上单击项目时崩溃(无法打开地图)。哪里出了问题?

提前感谢!!

编辑:已解决 感谢大家的评论。通过以下两种方式解决了此问题:1)将mapsfragment上的lateinit var更改为常规var + nullable,并且2)将main fragment中的bundle line更改为

val bundle = bundleOf(EXTRA_USER_MAP to sports[position])
view.findNavController(.navigate(R.id.action_mainFragment_to_mapsFragment, bundle)

我很激动,Kotlin太棒了!

主要碎片:

const val EXTRA_USER_MAP = "EXTRA_USER_MAP"
private const val TAG = "MainFragment"

class MainFragment : Fragment() {

override fun onCreateView ... // code to inflate my fragment view

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val sports = generateData()

        myMaps.layoutManager = LinearLayoutManager(activity)

        myMaps.adapter = this.context?.let {
            MapsAdapter(it, sports, object: MapsAdapter.OnClickListener {
                override fun onItemClick(position: Int) {
                    Log.i(TAG, "onItemClick $position")

                    // When user taps on view in recyclerview, navigate to new fragment and opens corresponding map
                    val bundle =  Bundle()
                    bundle.putSerializable(EXTRA_USER_MAP, sports[position])

                    view.findNavController().navigate(R.id.action_mainFragment_to_mapsFragment)
                }
            })
        }
    }
private fun generateData(): List<Sport> { ... // code for my data set

地图片段

private const val TAG = "MapsFragment"
class MapsFragment : Fragment(), OnMapReadyCallback {

    private lateinit var map: GoogleMap
    private lateinit var sport: Sport

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_maps, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val bundle = arguments
        if (bundle !=null) {
            sport = bundle.getSerializable(EXTRA_USER_MAP) as Sport
        }

        val mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment?
        mapFragment?.getMapAsync(this)
    }

    // Actions for map
    override fun onMapReady(googleMap: GoogleMap) {
        map = googleMap
        Log.i(TAG, "Map rendered: ${sport.title}") // Logcat check once working
...

相关适配器代码

class MapsAdapter(
    val context: Context,
    val sports: List<Sport>,
    val onClickListener: OnClickListener)
    : RecyclerView.Adapter<MapsAdapter.ViewHolder>() {

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)

    interface OnClickListener {
        fun onItemClick(position: Int)
    }
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val sport = sports[position]
        holder.itemView.setOnClickListener {
            Log.i(TAG, "Tapped on position $position")
            onClickListener.onItemClick(position)

        }
...

1
你没有将 Bundle 传递到 navigate 的调用中。你是不是想这样做? - ianhanniballake
抱歉,这会是什么样子?这可能就是它。 - wanderingThroughCode
阅读此链接:https://developer.android.com/guide/navigation/navigation-pass-data - kaustubhpatange
你已经学编程一个月了,进步这么大,太厉害了。哇! - Tayyab Mazhar
@kaustubhpatange 我按照捆绑指示进行操作,最终成功了!谢谢。 - wanderingThroughCode
1个回答

0
你可以创建一个共享的视图模型,在其中创建一个 LiveData 属性,并在 MainFragment 中更改其值,然后在 MapsFragment 中监听其变化,从而可以实现任何你想要的功能。或者,你也可以创建一个监听器来监听用户点击并获取位置信息。希望这对你有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接