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

RecyclerView不刷新:Room数据库数据仅在Fragment刷新后才展示

问题根因
  • 没有复用初始创建的RecyclerView Adapter实例,在子线程循环中每次新增数据都重新创建Adapter、重新绑定到RecyclerView,不仅性能低下,还会导致首次加载时的渲染时序异常,即使调用notifyDataSetChanged也无法正确作用到正确的Adapter实例上。
  • 数据库操作逻辑不合理:循环逐次查询单条数据、每次进入页面都重新构建Room数据库实例,拉长了数据加载耗时,同时子线程直接修改集合、主线程读取的操作存在并发读写风险。
  • 没有在数据全部加载完成后统一刷新UI,频繁的UI更新也可能导致首次渲染异常。
修复方案

第一步:修改Room DAO新增批量查询方法(在你的TodoDao接口中添加即可)

// TodoDao.kt 新增以下方法,注意替换为你实际的表名和实体类名
@Query("SELECT * FROM 你的训练表名")
fun getAllChosenWorkout(): List<你的训练实体类>

第二步:修改Fragment代码

class WorkoutFragment : Fragment() {

    private lateinit var homeViewModel: HomeViewModel
    private var _binding: FragmentWorkoutBinding? = null
    // 全局持有Adapter和数据集实例
    private lateinit var adapter: AdapterWorkoutsHeader
    private val workout: MutableList<String> = mutableListOf()
    private val workoutid: MutableList<Int> = mutableListOf()

    // This property is only valid between onCreateView and
    // onDestroyView.
    private val binding get() = _binding!!

    @SuppressLint("NotifyDataSetChanged")
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        homeViewModel =
            ViewModelProvider(this).get(HomeViewModel::class.java)

        _binding = FragmentWorkoutBinding.inflate(inflater, container, false)
        val root: View = binding.root
        val sharedPreference =  activity?.getSharedPreferences("WORKOUT_BUTTON", Context.MODE_PRIVATE)
        val sharedPreference2 =  activity?.getSharedPreferences("PREFERENCE_NAME", Context.MODE_PRIVATE)
        var editor = sharedPreference?.edit()
        val recyclerView = binding.recyclerview
        recyclerView?.layoutManager = LinearLayoutManager(context)
        
        workout.clear()
        workoutid.clear()
        // 初始化Adapter,直接持有数据集引用
        adapter = AdapterWorkoutsHeader(workoutid as ArrayList<Int>, workout as ArrayList<String>)
        recyclerView?.adapter = adapter


        val user = ParseUser.getCurrentUser()
        val parkname = user.get("parkname")
        val currentSpot: TextView = binding.currentSpot
        currentSpot.text = parkname.toString()
        val openNav: ImageButton = binding.openNav
        openNav.setOnClickListener {
            val mDrawerLayout: DrawerLayout? = activity?.findViewById(R.id.drawer_layout)
            mDrawerLayout!!.openDrawer(GravityCompat.START)
        }
        
        val addWorkout: Button = binding.button
        addWorkout.setOnClickListener {
            val intent = Intent(requireContext(), ChooseWorkoutActivity::class.java)
            startActivity(intent)
        }

        Thread{
            // 注意:建议后续把AppDatabase改为单例模式,不要每次都build实例,这里暂时保留原有写法
            val db = Room.databaseBuilder(
                requireContext(),
                AppDatabase::class.java, "workout.db"
            ).build()
            val userDao = db.todoDao()
            // 一次性查询所有数据,避免循环多次IO
            val allWorkout = userDao.getAllChosenWorkout()
            // 子线程先整理好临时数据
            val tempWorkout = mutableListOf<String>()
            val tempWorkoutId = mutableListOf<Int>()
            allWorkout.forEach { item ->
                item.workout?.let { tempWorkout.add(it) }
                item.workoutid?.let { tempWorkoutId.add(it) }
            }
            // 切主线程更新数据集+通知刷新
            activity?.runOnUiThread {
                workout.addAll(tempWorkout)
                workoutid.addAll(tempWorkoutId)
                adapter.notifyDataSetChanged()
            }
        }.start()

        return root
    }

    
    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

第三步:推荐优化项

  • 将AppDatabase改为单例模式,避免每次页面加载都重新构建数据库实例,大幅提升数据库操作性能。
  • 可改用Room的LiveData观察者模式监听数据变化,无需手动开启线程查询,数据变更时自动回调更新UI,适配增删改查后的自动刷新场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 02:21:00