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
相关产品推荐
相关产品推荐

