Kotlin实现RecyclerView搜索功能后旧数据残留,如何仅展示新查询数据?
问题根因
你的代码最大的问题是混用Navigation组件和手动Fragment事务,导致新旧Fragment的RecyclerView视图叠加,看起来像数据残留:
- 你已经通过
setupActionBarWithNavController、navView.setupWithNavController将导航逻辑交给了Navigation组件管理,R.id.nav_host_fragment是Navigation组件的宿主容器,内部Fragment的生命周期由NavController统一管控 - 你点击搜索按钮时直接调用
supportFragmentManager.beginTransaction().replace()修改NavHost内部的容器内容,会和Navigation本身的栈管理逻辑冲突,旧的Fragment视图没有被完全销毁,和新创建的RecordFragment的RecyclerView重叠展示,就出现了新数据叠在旧数据上的现象
修复方案
方案1:改用Navigation组件跳转(推荐)
- 首先在你的导航图xml文件中,给RecordFragment对应的目的地添加参数配置:
<fragment android:id="@+id/recordFragment" android:name="你的包名.RecordFragment"> <argument android:name="parameter" app:argType="string" android:defaultValue="A" /> </fragment>
- 修改MainActivity中搜索按钮的点击逻辑,用NavController跳转而非手动replace Fragment:
binding.btnSearch.setOnClickListener { val searchKey = if (binding.etSearch.text.isEmpty()) { "A" } else { binding.etSearch.text.toString() } val bundle = bundleOf("parameter" to searchKey) findNavController(R.id.nav_host_fragment).navigate(R.id.recordFragment, bundle) }
方案2:如果坚持用手动Fragment事务
需要先将NavHost中默认存在的初始Fragment全部移除,再添加新的RecordFragment,同时可以给RecyclerView设置非透明背景避免透色:
binding.btnSearch.setOnClickListener { val recordFragment = RecordFragment() val bundle = Bundle() val searchKey = if (binding.etSearch.text.isEmpty()) { "A" } else { binding.etSearch.text.toString() } bundle.putString("parameter", searchKey) recordFragment.arguments = bundle // 先清空NavHost容器内所有已有Fragment supportFragmentManager.fragments.forEach { supportFragmentManager.beginTransaction().remove(it).commit() } // 再添加新的Fragment supportFragmentManager.beginTransaction() .replace(R.id.nav_host_fragment, recordFragment) .commit() }
适配器优化(可选)
你的setList方法存在空指针风险,可以优化空判断逻辑,同时将列表声明为非空减少后续冗余判断:
// 把mRecord从可空改成非空 private val mRecord = arrayListOf<Event>() @SuppressLint("NotifyDataSetChanged") fun setList(data: List<Event>?) { mRecord.clear() data?.let { mRecord.addAll(it) } notifyDataSetChanged() }
内容的提问来源于stack exchange,提问作者happynewmind
相关产品推荐
相关产品推荐

