You need to enable JavaScript to run this app. 添加setFragmentResultListener后Fragment报did not return View错误如何解决
优惠活动
大模型
产品
解决方案
定价
更多

添加setFragmentResultListener后Fragment报did not return View错误如何解决

问题排查与解决方案

核心崩溃原因

你在onCreateView方法执行过程中调用了requireView(),但requireView()需要等onCreateView执行完成、返回根View之后才能正常调用,此时Fragment还未绑定根View,因此直接抛出IllegalStateException异常。
你已经提前通过inflater拿到了inflate后的view对象,直接用这个对象调用findViewById即可,不需要用requireView()。

其他潜在问题

  • store、amount、date三个TextView没有做初始化,后续直接调用setText会触发空指针崩溃
  • 同一个TableRow/TextView反复调用addView会抛出异常:每个View只能挂载到唯一的父布局上,不能重复添加
  • 遍历列表给同一个TextView赋值的逻辑无效,执行后只会显示列表的最后一个元素
  • 三个setFragmentResultListener逻辑高度重复,可合并简化

修正后的代码

class HistoryFragment : Fragment() {
    // 用数据类统一存储消费记录,避免分开维护三个列表
    data class ExpenseRecord(val store: String, val amount: String, val date: String)
    private val expenseList = mutableListOf<ExpenseRecord>()

    private lateinit var textview2: TextView
    private lateinit var textView3: TextView
    private lateinit var textView4: TextView
    private lateinit var table : TableLayout

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }
    
    override fun onCreateView(
        inflater: LayoutInflater, 
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        val view: View = inflater.inflate(R.layout.fragment_history, container, false)
        // 直接用刚inflate的view找控件,不要用requireView
        textview2 = view.findViewById(R.id.textView2)
        textView3 = view.findViewById(R.id.textView3)
        textView4 = view.findViewById(R.id.textView4)
        table = view.findViewById(R.id.tableHistorie)

        // 其他Fragment分三次返回数据的适配逻辑
        setFragmentResultListener("requestKey") { _, bundle ->
            val store = bundle.getString("bundleKey") ?: return@setFragmentResultListener
            addNewRow(store = store)
        }
        setFragmentResultListener("requestKey2") { _, bundle ->
            val amount = bundle.getString("bundleKey2") ?: return@setFragmentResultListener
            addNewRow(amount = amount)
        }
        setFragmentResultListener("requestKey3") { _, bundle ->
            val date = bundle.getString("bundleKey3") ?: return@setFragmentResultListener
            addNewRow(date = date)
        }
        
        // 可优化项:如果能修改另一个Fragment的逻辑,建议把三个参数塞到同一个Bundle返回,仅需一个监听即可
        // setFragmentResultListener("requestKey") { _, bundle ->
        //     val store = bundle.getString("bundleKey") ?: return@setFragmentResultListener
        //     val amount = bundle.getString("bundleKey2") ?: return@setFragmentResultListener
        //     val date = bundle.getString("bundleKey3") ?: return@setFragmentResultListener
        //     addNewRow(store, amount, date)
        // }

        return view
    }

    // 封装添加行的公共逻辑,避免重复代码
    private fun addNewRow(store: String = "", amount: String = "", date: String = "") {
        // 每次添加都新建行和TextView,不要复用同一个对象
        val newRow = TableRow(requireContext())
        val storeTv = TextView(requireContext()).apply { text = store }
        val amountTv = TextView(requireContext()).apply { text = amount }
        val dateTv = TextView(requireContext()).apply { text = date }
        newRow.addView(storeTv)
        newRow.addView(amountTv)
        newRow.addView(dateTv)
        table.addView(newRow)
        expenseList.add(ExpenseRecord(store, amount, date))
    }
}

后续优化建议

  • 如果后续需要展示的记录较多,建议用RecyclerView代替TableLayout实现列表,性能更好、拓展性更强
  • 尽量把同一份数据的参数合并到同一个Bundle中返回,减少冗余的监听逻辑
  • 可以给TextView设置统一的边距、样式,表格展示效果更规整

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 16:45:02