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

共享布局与代码的Fragment:组合替代继承的实现方案咨询

用组合模式实现Fragment的代码复用

核心思路

把Fragment中共享的视图初始化、通用配置逻辑抽离到一个独立的控制器类中,让每个具体Fragment通过持有该控制器的实例来复用逻辑,同时将各自差异化的部分(Adapter、回调)作为依赖传入控制器。

具体实现步骤

1. 创建共享视图控制器类

这个类负责处理所有通用的视图逻辑,比如布局绑定、RecyclerView基础配置、通用视图操作,并通过构造参数接收差异化的Adapter和回调:

class SharedFragmentController(
    private val rootView: View,
    private val recyclerAdapter: RecyclerView.Adapter<*>,
    private val itemClickCallback: (Any) -> Unit
) {
    private val titleTv: TextView = rootView.findViewById(R.id.title_tv)
    private val recyclerView: RecyclerView = rootView.findViewById(R.id.recycler_view)

    init {
        // 初始化通用RecyclerView配置
        recyclerView.layoutManager = LinearLayoutManager(rootView.context)
        recyclerView.adapter = recyclerAdapter
        // 绑定Adapter的点击事件到传入的回调
        setupAdapterClickListener()
    }

    private fun setupAdapterClickListener() {
        // 假设你的自定义Adapter都实现了点击监听接口,这里做类型判断并绑定
        if (recyclerAdapter is BaseClickableAdapter<*>) {
            recyclerAdapter.setOnItemClickListener { item ->
                itemClickCallback(item)
            }
        }
    }

    // 对外提供通用视图操作方法
    fun updateTitle(title: String) {
        titleTv.text = title
    }

    // 清理资源,避免内存泄漏
    fun cleanup() {
        if (recyclerAdapter is BaseClickableAdapter<*>) {
            recyclerAdapter.setOnItemClickListener(null)
        }
    }
}

// 自定义Adapter的基础接口(如果你的Adapter没有统一的点击监听,需要先定义)
interface BaseClickableAdapter<T> : RecyclerView.Adapter<*> {
    fun setOnItemClickListener(listener: ((T) -> Unit)?)
}

2. 实现具体Fragment

每个Fragment只需要处理自己的差异化逻辑,通过实例化控制器来复用通用代码:

FragmentA

class FragmentA : Fragment() {
    private lateinit var sharedController: SharedFragmentController

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

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        // 创建自己的Adapter
        val adapterA = AdapterA()
        // 定义自己的回调逻辑
        val clickCallback = { item: ItemA ->
            (activity as MainActivity).handleFragmentAItemClick(item)
        }

        // 初始化共享控制器,传入依赖
        sharedController = SharedFragmentController(view, adapterA, clickCallback)
        sharedController.updateTitle("Fragment A")
    }

    override fun onDestroyView() {
        super.onDestroyView()
        // 清理控制器资源
        sharedController.cleanup()
    }
}

FragmentB

class FragmentB : Fragment() {
    private lateinit var sharedController: SharedFragmentController

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

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        val adapterB = AdapterB()
        val clickCallback = { item: ItemB ->
            (activity as MainActivity).handleFragmentBItemClick(item)
        }

        sharedController = SharedFragmentController(view, adapterB, clickCallback)
        sharedController.updateTitle("Fragment B")
    }

    override fun onDestroyView() {
        super.onDestroyView()
        sharedController.cleanup()
    }
}

组合模式的优势

  • 低耦合:共享逻辑和差异化逻辑完全分离,修改共享逻辑不会影响具体Fragment的独立功能,反之亦然。
  • 灵活性高:如果后续新增类似Fragment,只需创建自己的Adapter和回调,复用同一个控制器即可,无需修改原有代码。
  • 避免继承陷阱:不会出现继承链过长、父类方法冗余、子类被迫继承不需要的逻辑等问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 12:54:19