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

Navigation跳转设置页返回后RecyclerView消失,报No adapter attached错误如何解决?

问题根因

你当前代码的核心问题是布局归属逻辑错位:RecyclerView、添加按钮这些组件都定义在HomeFragment的布局fragment_home.xml里,但你把这些组件的初始化、Adapter绑定逻辑全部写在了MainActivity中。
首次启动时MainActivity执行onCreate刚好赶上HomeFragment首次加载布局,findViewById能拿到当时的RecyclerView实例,绑定Adapter后可以正常展示;当你跳转到设置页再返回时,HomeFragment会重建自身的View树,生成新的RecyclerView实例,MainActivity中持有的还是已经销毁的旧实例,新的RecyclerView没有绑定过Adapter,就会输出你看到的警告,同时列表不显示。


修改方案

1. 精简MainActivity代码

删除MainActivity中所有和RecyclerView、添加FAB、Adapter相关的逻辑,仅保留导航、ViewModel初始化的部分,修改后代码如下:

package com.example.shoppinglist

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.findNavController
import androidx.navigation.ui.setupActionBarWithNavController

class MainActivity : AppCompatActivity() {
    lateinit var viewModel: ViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setupActionBarWithNavController(findNavController(R.id.fragment_main))
        // ViewModel保留在Activity级别,后续Fragment可以共享同一个实例
        val repository = Repository(Database(this))
        val factory = ViewModelFactory(repository)
        viewModel = ViewModelProvider(this, factory).get(ViewModel::class.java)
    }

    override fun onSupportNavigateUp(): Boolean {
        val navController = findNavController(R.id.fragment_main)
        return navController.navigateUp() || super.onSupportNavigateUp()
    }
}

2. 把列表逻辑迁移到HomeFragment中

HomeFragment需要负责自身布局内所有组件的初始化、Adapter绑定、事件处理,修改后代码如下:

package com.example.shoppinglist

import android.app.Dialog
import android.os.Build
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.Observer
import androidx.navigation.fragment.findNavController
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.floatingactionbutton.FloatingActionButton
import kotlinx.android_synthetic.main.fragment_home.*

class HomeFragment : Fragment(), RVAdapter.ListItemClickInterface {
    lateinit var RVAdapter: RVAdapter
    lateinit var viewModel: ViewModel

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

    @RequiresApi(Build.VERSION_CODES.N)
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        // 获取Activity级别的共享ViewModel
        viewModel = (requireActivity() as MainActivity).viewModel
        // 初始化RecyclerView
        val itemsRV = view.findViewById<RecyclerView>(R.id.recyclerView)
        val addFAB = view.findViewById<FloatingActionButton>(R.id.idFABAdd)
        RVAdapter = RVAdapter(emptyList(), this)
        itemsRV.layoutManager = LinearLayoutManager(requireContext())
        itemsRV.adapter = RVAdapter

        // 观察数据变化
        viewModel.getAllListItems().observe(viewLifecycleOwner, Observer {
            RVAdapter.list = it
            RVAdapter.notifyDataSetChanged()
        })

        // 添加按钮点击事件
        addFAB.setOnClickListener {
            openDialog()
        }

        // 设置按钮点击事件
        idFABSettings.setOnClickListener {
            findNavController().navigate(R.id.action_homeFragment_to_settingsFragment)
        }

        loadSettings()
    }

    @RequiresApi(Build.VERSION_CODES.N)
    private fun loadSettings(){
        val sp = PreferenceManager.getDefaultSharedPreferences(context)
        val theme = sp.getBoolean("theme_switch",false)
    }

    private fun openDialog() {
        val dialog = Dialog(requireContext())
        dialog.setContentView(R.layout.add_dialog)
        val cancelButton = dialog.findViewById<Button>(R.id.idBtnCancel)
        val addButton = dialog.findViewById<Button>(R.id.idBtnAdd)
        val itemEdt = dialog.findViewById<EditText>(R.id.idEditItemName)
        val itemQuantityEdt = dialog.findViewById<EditText>(R.id.idEditItemQuantity)

        cancelButton.setOnClickListener {
            dialog.dismiss()
        }
        addButton.setOnClickListener {
            val itemName: String = itemEdt.text.toString()
            val itemQuantity: String = itemQuantityEdt.text.toString()
            if (itemName.isNotBlank() && itemQuantity.isNotBlank()) {
                val items = ListItems(itemName, itemQuantity)
                viewModel.insert(items)
                Toast.makeText(requireContext(), "Item Added", Toast.LENGTH_SHORT).show()
                dialog.dismiss()
            } else {
                Toast.makeText(requireContext(), "Enter All Info To Add Item",
                    Toast.LENGTH_SHORT).show()
            }
        }
        dialog.show()
    }

    override fun onItemClick(listItems: ListItems) {
        viewModel.delete(listItems)
        Toast.makeText(requireContext(), "Item Deleted", Toast.LENGTH_SHORT).show()
    }
}

额外提示

你当前使用的kotlin-android-extensions已经被官方废弃,后续如果出现控件找不到的问题,可以替换为View Binding实现控件引用,稳定性更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 20:06:04