基于固定SharedPreferences键高效更新RecyclerView项及notifyItemChanged行为咨询
高效更新RecyclerView特定项的方案解析
核心结论
当SharedPreferences的固定键对应数据变化时,完全可以调用notifyItemChanged(position)来高效更新RecyclerView的特定项,这是最优方案之一——它只会重新绑定目标位置的ViewHolder,不会触发整个列表的重绘,性能开销远低于notifyDataSetChanged。
notifyItemChanged的行为逻辑
notifyItemChanged(position)的刷新逻辑完全依赖你传给Adapter的数据源数组:
- 调用该方法前,必须先更新数据源数组中对应位置的Item数据(比如从SharedPreferences读取最新值覆盖旧数据);
- 调用后,RecyclerView会重新调用
onBindViewHolder方法,读取数据源数组中该位置的最新数据来刷新UI; - 如果只调用
notifyItemChanged但未更新数据源,UI会刷新但显示的还是旧数据,因为onBindViewHolder读取的依然是数据源里的旧值。
结合SharedPreferences的实现步骤与代码示例
1. 定义数据模型
首先定义对应SharedPreferences键值对的数据类:
data class PreferenceItem(val key: String, var value: String)
2. 实现RecyclerView Adapter
Adapter直接基于数据源数组渲染UI:
class PreferenceAdapter(private val itemList: MutableList<PreferenceItem>) : RecyclerView.Adapter<PreferenceAdapter.ViewHolder>() { inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val keyTv: TextView = itemView.findViewById(R.id.tv_key) val valueTv: TextView = itemView.findViewById(R.id.tv_value) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.item_preference, parent, false) return ViewHolder(view) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val item = itemList[position] holder.keyTv.text = item.key holder.valueTv.text = item.value } override fun getItemCount() = itemList.size }
3. 业务逻辑层实现(Activity/Fragment)
初始化数据源、监听SharedPreferences变化并触发更新:
class MainActivity : AppCompatActivity() { private lateinit var sharedPrefs: SharedPreferences private lateinit var adapter: PreferenceAdapter private val itemList = mutableListOf<PreferenceItem>() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 初始化SharedPreferences sharedPrefs = getSharedPreferences("MyPrefs", MODE_PRIVATE) // 初始化数据源:加载固定键的初始值 val fixedKeys = listOf("user_name", "user_age", "user_email") fixedKeys.forEach { key -> val defaultValue = "" val value = sharedPrefs.getString(key, defaultValue) ?: defaultValue itemList.add(PreferenceItem(key, value)) } // 配置RecyclerView val recyclerView = findViewById<RecyclerView>(R.id.recycler_view) recyclerView.layoutManager = LinearLayoutManager(this) adapter = PreferenceAdapter(itemList) recyclerView.adapter = adapter // 监听SharedPreferences数据变化 val prefsChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { _, changedKey -> // 找到变化的键在数据源中的位置 val targetPosition = itemList.indexOfFirst { it.key == changedKey } if (targetPosition != -1) { // 1. 更新数据源中的对应项 val newValue = sharedPrefs.getString(changedKey, "") ?: "" itemList[targetPosition].value = newValue // 2. 通知Adapter刷新特定位置 adapter.notifyItemChanged(targetPosition) } } sharedPrefs.registerOnSharedPreferenceChangeListener(prefsChangeListener) } // 示例:修改SharedPreferences值的方法 private fun updatePrefValue(key: String, newValue: String) { sharedPrefs.edit().putString(key, newValue).apply() } }
关键注意事项
- 先更新数据源,再调用notifyItemChanged:这是保证UI显示最新数据的核心前提;
- 避免使用
notifyDataSetChanged:它会强制刷新整个列表,在数据量大时会造成明显的性能损耗; - 如果使用不可变数据源(如
List而非MutableList),可以通过创建新的列表实例替换旧数据源,再调用notifyItemChanged,效果一致。
内容的提问来源于stack exchange,提问作者Lol 123
相关产品推荐
相关产品推荐

