Filter实现原理及内部流程
来源:互联网 发布:武极天下坐骑进阶数据 编辑:程序博客网 时间:2024/06/14 10:32
一、Filter简介
APi中对Filter的描述极为精简,就是通过用户设置的过滤条件,通过Filter内部的一系列操作(对数据的过滤处理通常通过线程异步操作)实现过滤条件,最终获得过滤后的结果。一般通过实现Filterable接口调用(自定义的)Filter。
Filterable定义一过滤行为,利用Filter对数据进行过滤处理。Filterable通常实现对Adapt的限制。
Public interface Filterable{ //Returns a filter that can be used to constrain data with a filtering pattern. //This method is usually implemented by android.widget.Adapter classes. Filter getFilter();}
2、Filter
Filter通过定义的filter pattern实现对数据的过滤行为,对数据的过滤操作是异步实现的,通过调用filter(CharSequence)或filter(CharSequence, android.widget.Filter.FilterListener)实现,如果这两个方法被调用,先前还未被执行的异步操作将被取消,而只是执行此次调用的异步操作。Filter通常由Filterable创建,即Filter getFilter(),此处得到的Filter必然是用户自定义的,通常需要实现
FilterResults performFiltering(CharSequence constraint)
<pre name="code" class="java">publishResults(CharSequence,android.widget.Filter.FilterResults)
源码如下:
<pre name="code" class="java">public abstract class Filter { //执行异步过滤操作,调用此方法将会终止所有先前还未被执行的异步操作 public final void filter(CharSequence constraint) { filter(constraint, null); } //upon completion of the operation,the listener is notified public final void filter(CharSequence constraint, FilterListener listener) //在线程中调用该方法,根据提供的 constraint执行过滤操作,该操作返回FilterResults //在UI线程中,通过调用publishResults(CharSequence,android.widget.Filter.FilterResults)返回FilterResults protected abstract FilterResults performFiltering(CharSequence constraint); //在线程中调用此函数,将过滤后的结果FilterResults更新到UI界面, protected abstract void publishResults(CharSequence constraint,FilterResults results); //将过滤后的Item转换成字符串,根据实际需要重写 public CharSequence convertResultToString(Object resultValue) { return resultValue == null ? "" : resultValue.toString(); } //保存过滤操作后得到的结果,实际上就是一个数据封装 protected static class FilterResults { public FilterResults() { } // Contains all the values computed by the filtering operation. //一般是数组或Arraylist public Object values; //values个数 public int count; } //Listener used to receive a notification upon completion of a filtering operation public static interface FilterListener { //Notifies the end of a filtering operation public void onFilterComplete(int count); }}
二、AutoCompleteTextView利用ArrayAdapter实现提示原理
实现一个完整的Filter流程,一般是两个步骤:一是实现对数据的过滤操作,获得过滤结果后,通过观察者模式获知数据发生变化,并进行后续处理;二是在过滤操作完成后,调用监听器接口实现自定义操作:public static interface FilterListener
ArrayAdapter实现继承自Filter的内部类ArrayFilter,主要是实现两个函数:performFiltering,主要是对ArrayAdapter中的数据项实现对某个前缀的匹配操作,并获得匹配的数据项;publishResults,获得符合过滤条件的结果后,通过观察者模式,实现刷新等操作。
public class ArrayAdapter<T> extends BaseAdapter implements Filterable { public Filter getFilter() { if (mFilter == null) { mFilter = new ArrayFilter(); } return mFilter; } /** * An array filter constrains the content of the array adapter with a prefix. * Each item that does not start with the supplied prefix is removed from the list. */ private class ArrayFilter extends Filter { @Override protected FilterResults performFiltering(CharSequence prefix) { FilterResults results = new FilterResults(); if (mOriginalValues == null) { synchronized (mLock) { mOriginalValues = new ArrayList<T>(mObjects); } } if (prefix == null || prefix.length() == 0) { ArrayList<T> list; synchronized (mLock) { list = new ArrayList<T>(mOriginalValues); } results.values = list; results.count = list.size(); } else { String prefixString = prefix.toString().toLowerCase(); ArrayList<T> values; synchronized (mLock) { values = new ArrayList<T>(mOriginalValues); } final int count = values.size(); final ArrayList<T> newValues = new ArrayList<T>(); for (int i = 0; i < count; i++) { final T value = values.get(i); final String valueText = value.toString().toLowerCase(); // First match against the whole, non-splitted value if (valueText.startsWith(prefixString)) { newValues.add(value); } else { final String[] words = valueText.split(" "); final int wordCount = words.length; // Start at index 0, in case valueText starts with space(s) for (int k = 0; k < wordCount; k++) { if (words[k].startsWith(prefixString)) { newValues.add(value); break; } } } } results.values = newValues; results.count = newValues.size(); } return results; } @Override protected void publishResults(CharSequence constraint, FilterResults results) { //noinspection unchecked mObjects = (List<T>) results.values; if (results.count > 0) { notifyDataSetChanged(); } else { notifyDataSetInvalidated(); } }}
2、AutoCompleteTextView
实现Filter中的接口Filter.FilterListener
public class AutoCompleteTextView extends EditText implements Filter.FilterListener { public void onFilterComplete(int count) { updateDropDownForFilter(count); } private void updateDropDownForFilter(int count) { // Not attached to window, don't update drop-down if (getWindowVisibility() == View.GONE) return; /* * This checks enoughToFilter() again because filtering requests * are asynchronous, so the result may come back after enough text * has since been deleted to make it no longer appropriate * to filter. */ final boolean dropDownAlwaysVisible = mPopup.isDropDownAlwaysVisible(); final boolean enoughToFilter = enoughToFilter(); if ((count > 0 || dropDownAlwaysVisible) && enoughToFilter) { if (hasFocus() && hasWindowFocus() && mPopupCanBeUpdated) { showDropDown(); } } else if (!dropDownAlwaysVisible && isPopupShowing()) { dismissDropDown(); // When the filter text is changed, the first update from the adapter may show an empty // count (when the query is being performed on the network). Future updates when some // content has been retrieved should still be able to update the list. mPopupCanBeUpdated = true; } }
三、自定义Filter
ArrayAdapter只能实现一个TextView,通过自定义一个ContactAdapter,实现两个TextView,配合AutoCompleteTextview使用
自定义ContactAdapter:
package com.study.contactadapter;import java.util.ArrayList;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.Filter;import android.widget.Filterable;import android.widget.TextView;import com.example.autotipphonenumber.R;import com.study.remind.Contact;public class ContactAdapter extends BaseAdapter implements Filterable{private Context context;private ArrayList<Contact> Datas;private LayoutInflater inflater;public ContactAdapter(Context context,ArrayList<Contact> Datas){this.context=context;this.Datas=Datas;//设置inflater的两种方式//inflater=(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);inflater=LayoutInflater.from(context);}@Overridepublic int getCount() {// TODO Auto-generated method stubreturn Datas.size();}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stubreturn Datas.get(position);}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {View root = inflater.inflate(R.layout.contcat,null);TextView name=(TextView) root.findViewById(R.id.name);TextView phoneNum=(TextView) root.findViewById(R.id.phoneNum);name.setText(Datas.get(position).getName());phoneNum.setText(Datas.get(position).getPhoneNum());return root;}//实现Filterabale接口@Overridepublic Filter getFilter() {return new ContactFilter();}private class ContactFilter extends Filter{@Override//两个textview中的任意一个<span style="font-family: KaiTi_GB2312;">首字母符合过滤条件,则将其加入到过滤结果中</span>
protected FilterResults performFiltering(CharSequence constraint) {FilterResults results = new FilterResults();ArrayList<Contact> filterResult=new ArrayList<Contact>();for(int i=0;i<Datas.size();i++){if(Datas.get(i).getName().startsWith((String) constraint) || Datas.get(i).getPhoneNum().startsWith((String) constraint) ){filterResult.add(Datas.get(i));}} results.values = filterResult; results.count = filterResult.size();return results;}@Overrideprotected void publishResults(CharSequence constraint,FilterResults results) { if (results.count > 0) { notifyDataSetChanged(); } else { notifyDataSetInvalidated(); }}}}
MainActivity源码:
package com.example.autotipphonenumber;import java.util.ArrayList;import android.app.Activity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.AdapterView.OnItemSelectedListener;import android.widget.AutoCompleteTextView;import com.study.contactadapter.ContactAdapter;import com.study.remind.Contact;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);final AutoCompleteTextView autoTip=(AutoCompleteTextView) this.findViewById(R.id.autoTip);autoTip.setThreshold(1);//初始化数据ArrayList<Contact> Contacts=Contact.generateContact();//自定义adapterContactAdapter adapter=new ContactAdapter(this,Contacts);autoTip.setAdapter(adapter);//设置点击事件获取文本autoTip.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id) {Contact contact=(Contact) parent.getItemAtPosition(position);autoTip.setText(contact.getPhoneNum());}});}}
结果:
- Filter实现原理及内部流程
- Bloom Filter 原理 及C++ 实现
- Bloom Filter的原理及实现
- IntentService实现原理及内部代码
- IntentService实现原理及内部代码
- IntentService实现原理及内部代码
- Elasticsearch2.x Filter执行流程及缓存原理
- Pegasus间谍套件内部原理及流程剖析
- LRUCache原理及HashMap LinkedHashMap内部实现原理
- SDWebImage底层实现原理及内部实现过程
- SDWebImage底层实现原理及内部实现过程
- SDWebImage底层实现原理及内部实现过程
- Filter原理及应用
- Filter原理及应用
- 二级域名原理、实现流程及程序
- Activiti HelloWorld流程实现及原理
- Filter原理及实现批量设置请求编码
- 布隆过滤器(Bloom Filter)原理及python实现
- 查看内核版本
- 16进制
- FreeRTOS 操作系统介绍
- cocos2dx-3.1 接入多盟广告sdk+Android (1)
- sublime text 3 快捷键
- Filter实现原理及内部流程
- POJ 2993:Emag eht htiw Em Pleh
- emulator: ERROR: x86 emulation currently requires hardware acceleration!Please ensure Intel HAXM is
- 写给计算机的大学生
- LinkedList基本用法
- linux定时任务crontab配置
- [ 2015多校联合训练赛 hdu 5308 I Wanna Become A 24-Point Master 2015 Multi-University Training Contest 2 模拟题
- CSS使用overflow隐藏超出范围的内容
- Creo二次开发个人二维码上线了。