我正在提高应用程序的稳定性和性能,但现在我被困在Android Studio的警告中。请考虑以下适配器类:
private class CoinsAdapter(private val fragment: CoinFragment, private val coins: List<Coin>): RecyclerView.Adapter<CoinsAdapter.ViewHolder>(), Filterable {
private val filter = ArrayList(coins)
override fun onCreateViewHolder(parent: ViewGroup, position: Int): ViewHolder {
val binding = ItemCoinBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val coin = filter[position]
holder.binding.coinImage.setImageResource(coin.image)
holder.binding.coinText.text = builder.toString()
}
override fun getItemCount() = filter.size
override fun getFilter() = object : Filter() {
override fun performFiltering(constraint: CharSequence): FilterResults {
if (constraint.length < 2) return fetchResults(coins)
val pattern = constraint.toString().lowercase().trim()
val filter = arrayListOf<Coin>()
for (coin in coins) if (coin.name.lowercase().contains(pattern)) filter.add(coin)
return fetchResults(filter)
}
private fun fetchResults(coins: List<Coin>): FilterResults {
val results = FilterResults()
results.values = coins
return results
}
override fun publishResults(constraint: CharSequence, results: FilterResults) {
filter.clear()
filter.addAll(results.values as List<Coin>)
notifyDataSetChanged()
}
}
private inner class ViewHolder(val binding: ItemCoinBinding) : RecyclerView.ViewHolder(binding.root)
}
适配器和过滤器工作正常,但是请注意< code>publishResults函数。Android Studio警告说,关于< code > notifyDataSetChanged 。
如果可以的话,使用更具体的更改事件将始终更有效。依靠 notifyDataSetChanged 作为最后的手段。
但是,我不知道如何在这个实例中使用< code > notifyDataSetChanged (带有过滤器)。在这种情况下,什么是正确的方法以及如何使用它?
< code > notifyDataSetChanged 重绘整个视图,这就是Android Studio显示警告的原因。
要摆脱这种情况,您可以使用DiffUtil
private class CoinsAdapter(private val fragment: CoinFragment, private val coins: List<Coin>): RecyclerView.Adapter<CoinsAdapter.ViewHolder>(FilterDiffCallBack()), Filterable {
....
....
//This check runs on background thread
class FilterDiffCallBack: DiffUtil.ItemCallback<Post>() {
override fun areItemsTheSame(oldItem: Coin, newItem: Coin): Boolean {
return oldItem.someUniqueId == newItem.someUniqueId
}
override fun areContentsTheSame(oldItem: Coin, newItem: Coin): Boolean {
return oldItem == newItem
}
}
...
...
override fun publishResults(constraint: CharSequence, results: FilterResults) {
submitList(results)// call the DiffUtil internally
}
}
如果列表中的数据主要随着用户交互而改变,那么您可以使用像< code > notifyItemChanged(int) 、< code > notifyItemInserted(int) 、< code > notifyItemRemoved(int)等方法,因为这是更新视图最有效的方法。更多信息请点击此处
据我所知,将可过滤界面与 RecyclerView.Adapter 一起使用是没有意义的。Filterable 旨在 AdapterView Adapters 中使用,因为有一些小部件可以检查适配器是否为可过滤适配器,并且可以自动提供一些过滤功能。但是,RecyclerView.Adapter 与 AdapterView 的 Adapter 没有任何关系。
如果您愿意,您仍然可以使用Filter接口来组织您的代码,但是对我来说,这似乎是多余的样板文件。我在StackOverflow上看到过其他老答案说在RecyclerView中实现Filterable。适配器,但我认为他们这样做是出于使用旧适配器类的习惯。
至于在过滤时提高适配器的性能,有几个选择。
>
使用 SortedList 和 SortedList.Callback 来管理您的列表。回调可以让您实现一堆函数来通知特定项目或项目范围的更改,而不是一次通知整个列表。我没有使用过这个,而且似乎有很多地方出错,因为有太多的回调函数要实现。这也是一吨的样板。这里最重要的答案描述了如何做到这一点,但它已经有几年的历史了,所以我不知道是否有更新的方法。
从ListAdapter扩展您的适配器。ListAdapter的构造函数采用DiffUtil。ItemCallback参数。回调告诉它如何比较两个项目。只要您的模型项具有惟一的ID属性,这就很容易实现。使用ListAdapter时,不要在类中创建自己的List属性,而是让超类来处理。然后,不是设置一个新的筛选列表并调用< code > notifyDataSetChanged(),而是使用您的筛选列表调用< code > adapter . submit list(),它使用DiffUtil自动只更改必要的视图,并且它还使用漂亮的动画来完成它。注意您也不需要重写< code>getItemCount(),因为超类拥有该列表。
由于您正在筛选项目,因此您可能希望保留一个额外的属性来存储原始的未筛选列表,并在应用新筛选器时使用它。因此,我在此示例中创建了一个额外的列表属性。您需要小心,不要仅使用它来传递到 submitList(),
并始终在 onBindViewHolder()
中使用 currentList
,因为 currentList
是适配器实际用来显示的内容。
我删除了Filterable函数,这样外部类就可以简单地设置< code>filter属性。
class CoinsAdapter : ListAdapter<Coin, CoinsAdapter.ViewHolder>(CoinItemCallback) {
object CoinItemCallback : DiffUtil.ItemCallback<Coin>() {
override fun areItemsTheSame(oldItem: Coin, newItem: Coin): Boolean = oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: Coin, newItem: Coin): Boolean = oldItem == newItem
}
var coins: List<Coin> = emptyList()
set(value) {
field = value
onListOrFilterChange()
}
var filter: CharSequence = ""
set(value) {
field = value
onListOrFilterChange()
}
override fun onCreateViewHolder(parent: ViewGroup, position: Int): ViewHolder {
val binding = ItemCoinBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val coin = currentList[position]
holder.binding.coinImage.setImageResource(coin.image)
holder.binding.coinText.text = builder.toString()
}
private fun onListOrFilterChange() {
if (filter.length < 2) {
submitList(coins)
return
}
val pattern = filter.toString().lowercase().trim()
val filteredList = coins.filter { pattern in it.name.lowercase() }
submitList(filteredList)
}
inner class ViewHolder(val binding: ItemCoinBinding) : RecyclerView.ViewHolder(binding.root)
}
这个项目是可以在Android Studio中找到的Master/Detail流模板的扩展。不同之处在于,这个应用程序使用一个活动和一个管理三个片段的ViewPager。第三个片段是Master(list)片段,其中包含一个可单击的Recyview。当单击列表项时,它会用子(细节)片段切换该片段。 在项目工作时,我希望避免在清单中使用。我该怎么做? baseFragment.java 接口:bri
我目前有一个Rabbit MQ Broker设置,带有直接交换,我使用Spring Integration来生成和使用队列中的消息。我使用的是责任链模式,其中我使用SI将消耗的消息从一个POJO传递到另一个POJO。为此,我使用了一个Spring Integration入站通道适配器。这要求它具有对轮询器的引用。 如何移除轮询器,使其不在轮询机制上工作,而是使用回调,以便一旦消息可用,它将从队列中
问题内容: 我已经检查了所有其他问题,并发现了相同的错误,但没有找到有帮助的解决方案= / 我有一个字典列表: 其中某些值为空。创建这些列表结束时,我想在返回字典之前删除这些空列表。当前,我正在尝试执行以下操作: 但是,这给了我运行时错误。我知道您无法在字典中进行迭代时添加/删除字典中的元素…那么解决这个问题的方法是什么? 问题答案: 在Python 2.x中,调用会生成密钥的副本,您可以在修改时
我有下面的servlet过滤器。
问题内容: 我有一个扩展ExpandableListActivity的活动。我使用SimpleCursorTreeAdapter填充ExpandableListView。我的布局包含列表视图和空视图。在应用启动时,ExpandableListActivity自动选择要显示的右视图。 我的步骤: 应用启动,没有数据。(屏幕上的空白视图) 将一些数据插入db。 调用adapter.notifyData
我正在 pyspark 中对 (x,y) 点的 RDD 实现范围查询。我将 xy 空间划分为一个 16*16 的网格(256 个单元格),并将 RDD 中的每个点分配给其中一个单元格。gridMappedRDD 是一个 PairRDD: 我将这个RDD分区为256个分区,使用: 范围查询是一个矩形框。我为我的网格对象准备了一个方法,它可以返回与查询范围重叠的单元格id列表。所以,我用这个作为过滤器