You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中实现RecyclerView点击跳转详情Fragment并传递数据

文章列表跳转详情页实现方案

效果示例

界面示例

核心问题梳理

原有代码存在3个逻辑错误:

  • Adapter内点击事件仅创建了Article对象,未向外传递点击事件、未触发跳转逻辑
  • Fragment间传参错误使用了Activity跳转的Intent API,Fragment传参需要通过arguments Bundle携带数据
  • 列表所在的HomeFragment中未实现Fragment跳转调度逻辑

分步实现

1. 配置Article实体类支持序列化

确保Article实体类实现Parcelable接口,支持组件间数据传递,Kotlin可直接用@Parcelize注解简化模板代码:

import android.os.Parcelable
import kotlinx.parcelize.Parcelize

@Parcelize
data class Article(
    val title: String,
    val img: String,
    val content: String
) : Parcelable

注意:使用@Parcelize需要在模块级build.gradle的plugins块中添加id 'kotlin-parcelize'插件

2. 修改ArticleAdapter,增加点击事件回调

Adapter不直接持有Fragment导航能力,通过高阶函数将点击事件抛给外层宿主处理,避免代码耦合:

class ArticleAdapter(private val articleList: ArrayList<Article>) :
    RecyclerView.Adapter<ArticleAdapter.MyViewHolder>() {

    // 声明点击事件回调,入参为被点击的文章对象
    private var onItemClickListener: ((Article) -> Unit)? = null

    // 对外提供监听设置入口
    fun setOnItemClickListener(listener: (Article) -> Unit) {
        onItemClickListener = listener
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val binding = ItemArticleBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return MyViewHolder(binding)
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val data = articleList[position]
        holder.bind(data, onItemClickListener)
    }

    class MyViewHolder(private val binding: ItemArticleBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind(data: Article, clickListener: ((Article) -> Unit)?) {
            Glide.with(binding.root.context)
                .load(data.img)
                .into(binding.articleImage)
            binding.articleTitle.text = data.title

            binding.root.setOnClickListener {
                // 点击时触发回调,传入当前条目对应的文章数据
                clickListener?.invoke(data)
            }
        }
    }

    override fun getItemCount(): Int = articleList.size
}

3. 改造DetailArticleFragment,通过arguments接收参数

删除原有错误的Intent取值逻辑,通过Fragment自带的arguments获取参数,新增newInstance工厂方法统一传参入口,避免外部写错参数Key:

class DetailArticleFragment : Fragment() {
    private var _binding: FragmentDetailArticleBinding? = null
    private val binding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentDetailArticleBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // 从arguments中获取序列化的文章对象,做合法性校验
        val article = arguments?.getParcelable<Article>(DETAIL_ARTICLE)
            ?: throw IllegalArgumentException("缺少文章参数,无法打开详情页")
        
        // 渲染页面数据
        Glide.with(this)
            .load(article.img)
            .into(binding.articleImage)
        binding.articleTitle.text = article.title
        binding.articleDescription.text = article.content
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
    companion object {
        private const val DETAIL_ARTICLE = "detail_article"

        // 统一传参入口
        fun newInstance(article: Article): DetailArticleFragment {
            val fragment = DetailArticleFragment()
            val bundle = Bundle().apply {
                putParcelable(DETAIL_ARTICLE, article)
            }
            fragment.arguments = bundle
            return fragment
        }
    }
}

4. 在HomeFragment中实现跳转调度

在HomeFragment初始化RecyclerView的位置,给Adapter设置点击监听,点击条目时执行Fragment跳转:

// HomeFragment中初始化Adapter的代码段
val articleAdapter = ArticleAdapter(articleList)
// 设置条目点击监听
articleAdapter.setOnItemClickListener { clickedArticle ->
    // 两种跳转方式二选一即可
    // 方式1:使用Navigation组件导航(推荐)
    val bundle = bundleOf(DetailArticleFragment.DETAIL_ARTICLE to clickedArticle)
    findNavController().navigate(R.id.action_homeFragment_to_detailArticleFragment, bundle)

    // 方式2:使用原生FragmentTransaction跳转
    // parentFragmentManager.beginTransaction()
    //     .replace(R.id.fragment_container, DetailArticleFragment.newInstance(clickedArticle))
    //     .addToBackStack(null)
    //     .commit()
}
// 给RecyclerView绑定adapter
binding.articleRv.adapter = articleAdapter

注意事项

  • 如果使用Navigation组件跳转,不需要手动调用newInstance方法,直接通过bundle传参即可,Navigation会自动将bundle设置为目标Fragment的arguments
  • 不要在Adapter中直接执行Fragment跳转逻辑,会造成代码耦合、提升内存泄漏风险
  • 接收参数时必须做好判空校验,避免因参数缺失导致崩溃

内容的提问来源于stack exchange,提问作者micinable

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 18:42:25