今天就跟大家聊聊有关如何在Android中利用Filterable对Recyclerview进行筛选,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
实现步骤
class MyBean(var type:String,var name:String,var deliverType:String)
这里我们简单的创建个数据Bean类,后面我们的筛选字段是根据type和deliverType来进行筛选。
class MyAdapter(data: MutableList<MyBean>) : RecyclerView.Adapter<MyAdapter.MyViewHolder>(), Filterable { //存放原数据 private var mSourceList = mutableListOf<MyBean>() //存放过滤后的数据 private var mFilterList = mutableListOf<MyBean>() init { mSourceList = data } override fun onBindViewHolder(holder: MyViewHolder, position: Int) { holder.name.text = mFilterList[position].name holder.deliverType.text = mFilterList[position].deliverType } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { var view = LayoutInflater.from(parent.context).inflate(R.layout.item, parent, false) return MyViewHolder(view) } /** * 注意:这里返回过滤后的集合大小 */ override fun getItemCount(): Int { return mFilterList.size } inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { //商品名称 var name: TextView = itemView.findViewById(R.id.tvName) //配送方式 var deliverType: TextView = itemView.findViewById(R.id.tvDeliverType) } }
和我们平时创建的Adapter没什么两样。但要注意以下几点
1、这里我们创建了两个集合mSourceList和mFilterList,mFilterList主要是用来存放过滤后的数据,而mSourceList主要是用来在筛选后数据恢复时使用,使得不用再去请求一次数据。
2、getItemCount()方法返回过滤后的集合的大小。
有个疑问:
假如我们没有进行过滤,而因为我们的mFilterList默认为空,且getItemCount()返回的是它的大小0,那我们默认是不是就显示不出数据?
1、继承Filterable接口后,实现其getFilter()方法,该方法需要我们返回一个Filter过滤器对象。
2、我们重写Filter的performFiltering()方法和publishResults()方法,performFiltering()用来实现我们具体过滤的逻辑操作,publishResults()用来将我们过滤后的数据进行更新。
3、因为performFiltering()传来的过滤条件是一段字符串,而我们的过滤条件有两个,所以我们将过滤的条件转化为Json对象传过来,那样就可以得到多个过滤条件的字符串了。
4、这里我们的具体过滤操作是使用Collection的filter()方法进行过滤
(1)当condition1和condition2为空时,返回原数据mSourceList
(2)否则使用filter()方法按条件进行过滤,最后将过滤后的集合赋值给FilterResults()对象的value字段,并将其返回
5、publishResults(charSequence: CharSequence,filterResults: FilterResults)方法中filterResults对象内的value字段是我们performFiltering()方法返回的过滤后的集合,在这里我们将RecyclerView进行更新。
具体实现见以下代码:
class MyAdapter(data: MutableList<MyBean>) : RecyclerView.Adapter<MyAdapter.MyViewHolder>(), Filterable { /** * 具体的执行过滤的操作 * 创建适配器后会默认的执行一次 */ override fun getFilter(): Filter { return object : Filter() { //执行过滤操作 override fun performFiltering(charSequence: CharSequence): FilterResults { val charString = charSequence.toString() Log.i(TAG, "performFiltering: 执行过滤操作,过滤字段为:$charString") val jsonObject = JSONObject(charString) //筛选条件一 var condition1 = jsonObject.getString("condition1") //筛选条件二 var condition2 = jsonObject.getString("condition2") //存放已过滤的数据 var theFilterList = if (condition1.isEmpty() && condition2.isEmpty()) { //没有过滤的内容,则使用源数据 mSourceList } else if (condition2.isEmpty()) { mSourceList.filter { it.type == condition1 } } else if (condition1.isEmpty()) { mSourceList.filter { it.deliverType == condition2 } } else { mSourceList.filter { it.type == condition1 && it.deliverType == condition2 } } val filterResults = FilterResults() filterResults.values = theFilterList return filterResults } //把过滤后的值返回出来并进行更新 override fun publishResults( charSequence: CharSequence, filterResults: FilterResults ) { mFilterList = filterResults.values as MutableList<MyBean> notifyDataSetChanged() } } } }
class MainActivity : AppCompatActivity() { //过滤条件1 var condition1 = "" //过滤条件2 var condition2 = "" //总的过滤条件 var jsonObject = JSONObject() private var dataList = mutableListOf<MyBean>() var myAdapter = MyAdapter(dataList) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) mRecyclerView.layoutManager = LinearLayoutManager(this) mRecyclerView.adapter = myAdapter jsonObject.put("condition1","过滤条件一") jsonObject.put("condition2","过滤条件二") myAdapter.filter.filter(jsonObject.toString()) } }
如果想恢复数据不筛选,直接将jsonObject对象内的condition1和condition2字段设为空,然后调用myAdapter.filter.filter(jsonObject.toString())即可。
具体见代码
其实我们getFilter()内的过滤操作还可以优化下
var theFilterList = if (condition1.isEmpty() && condition2.isEmpty()) { //没有过滤的内容,则使用源数据 mSourceList } else if (condition2.isEmpty()) { mSourceList.filter { it.type == condition1 } } else if (condition1.isEmpty()) { mSourceList.filter { it.deliverType == condition2 } } else { mSourceList.filter { it.type == condition1 && it.deliverType == condition2 } }
可以看到else{}下是当condition1和condition2都不为空的情况下进行的筛选,但是如果我们使用下拉框进行筛选时,选择第一个条件condition1后就已经进行了一次筛选,即condition1不为空condition2为空,在 else if (condition2.isEmpty()){} 里对源数据进行了筛选;再选择第二个条件时,又进行了一次筛选,即condition1不为空condition2不为空,在else{}里又是对源数据进行筛选,其实我们应该是在第一次的结果下进行筛选是最优的办法。
想法很好,但实现起来困难挺多,在两个条件都不为空时,我们需要判断第一次删选下来的数据是以哪个筛选条件为依据的,在两个条件都不为空筛选后,再次更改其中一个筛选条件,我们需要先将另外一个筛选条件下的数据给筛选出来,越来越麻烦,暂时不考虑了,有好的方案的麻烦给个思路。
因为Adapter默认返回的大小是筛选后的尺寸,而我们默认是没有筛选的,导致上来会没有数据,所以我们需要设置适配器后,人为的调用一下筛选才好:myAdapter.filter.filter(jsonObject.toString())。而我在项目中没有写因为AppCompatSpinner会默认的选择第0项,我在其onItemSelected()回调里调用了筛选功能。
看完上述内容,你们对如何在Android中利用Filterable对Recyclerview进行筛选有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。