今天就跟大家聊聊有關如何在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進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。