一、何谓Android的过滤机制?
Android对数据的处理是分层的,从上到下,可以分为:数据层、提供层、Cursor层(不好意思,没找到一个词来表示)、适配层、显示层。每个层次通过一定的机制,可以使数据发生变化时能够上下通知。如下图:
- 显示层(ListView,GridView,AutoCompleteTextView等)
- 适配层(Adpater)
- Cursor层(Cursor)
- 提供层(ContentProvider)
- 数据层(文件、sqlite、SharedPreference)
数据层是数据具体的存储方式,它可以包括文件、sqlite数据库以及SharedPreference。提供层向上层提供了统一的数据调用方式,并负责向其它应用共享数据。Cursor层将查询的数据统一成Cursor的形式来使用。适配层用来连接Cursor层和显示层,将数据和界面连接起来。显示层负责数据的显示。
另外,Andriod提供了数据的过滤机制,也就是在不改变数据存储的情况下,异步或同步的过滤符合条件的数据,并即时的显示在界面上。
Android原生的例子当中,最明显的例子就是AutoCompleteTextView
当输入“C程”时,数据库中自动过滤出了还有该字符串的联系人姓名,并显示出来。
二、Android做了哪些?
- 为了实现数据的过滤,andorid设计了抽象类Filter,进行异步和同步的数据过滤操作。
- 在Adapter中继承Filterable,提供给使用者Filter,进行过滤。
- 在不同的View中,获得查询约束字符串,传递给Adapter,并且提供配合数据过滤的界面支持。
三、Filter类
Filter的使用流程如下:
调用filter方法->在另一线程中调用performFiltering进行数据查询->得到数据过滤结果后调用publishResults将结果返回到使用它的客户端。
该类中的performFiltering和publishResults均为抽象方法,需要继承者自己重写。
四、Filterable接口
常用的Adapter基本上都继承了Filterable接口,如CursorAdapter,ArrayAdapter,SimpleAdapter等。该接口只有一个函数,名为getFilter,通过该函数可以通过Adaper获取Filter,然后通过该Filter进行过滤。
五、数据过滤功能的View的界面支持。
为了实现数据过滤的功能,在数据显示层,也有相应的支持。比如ListView和GridView,设置了setFilterText函数,通过该函数可以一方面进行数据的过滤,另一方面显示一个PopupWindow,提示用户输入了那种过滤条件。AutoCompleteTextView当用户在文本框输入文字时,自动进行过滤,并弹出列表显示过滤数据。
六、实战
MainActivity如下:
package cc.testfilterable;
import java.util.ArrayList;
import java.util.HashMap;
import android.os.Bundle;
import android.widget.ListView;
import android.app.Activity;
import android.content.Context;
/**
* Demo描述:
* 利用Filter过滤数据
* 可用于AutoCompleteTextView筛选数据等功能
*
* 备注说明:
* 该Demo只表述原理,代码逻辑较简单,有一些小的bug.
* 完整的应用请参见以下资料.
*
* 参考资料:
* 1 http://gundumw100.iteye.com/blog/1446507
* 2 http://blog.csdn.net/ssstudio/article/details/7579089
* 3 http://blog.csdn.net/jiahui524/article/details/7802033
*
*/
public class MainActivity extends Activity {
private Context mContext;
private ListView mListView;
private ListViewAdapter mListViewAdapter;
private ArrayList<String> mArrayList;
private HashMap<String, String> mHashMap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
init();
}
private void init(){
mContext=this;
mListView=(ListView) findViewById(R.id.listView);
mArrayList=new ArrayList<String>();
mArrayList.add("张三1");
mArrayList.add("李四1");
mArrayList.add("王五1");
mArrayList.add("张三2");
mArrayList.add("李四2");
mArrayList.add("王五2");
mArrayList.add("张三3");
mArrayList.add("李四3");
mArrayList.add("王五3");
mArrayList.add("张三4");
mArrayList.add("李四4");
mArrayList.add("王五4");
mListViewAdapter=new ListViewAdapter(mContext, mArrayList);
//过滤数据
//过滤出姓名里面包含"张"的数据
mListViewAdapter.getFilter().filter("张");
mListView.setAdapter(mListViewAdapter);
}
}
ListViewAdapter如下:
package cc.testfilterable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
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.TextView;
public class ListViewAdapter extends BaseAdapter {
private NameFilter mNameFilter;
private List<String> mArrayList;
private List<String> mFilteredArrayList;
private LayoutInflater mLayoutInflater;
public ListViewAdapter(Context context,List<String> arrayList) {
mArrayList = arrayList;
mLayoutInflater=LayoutInflater.from(context);
mFilteredArrayList=new ArrayList<String>();
}
@Override
public int getCount() {
if (mArrayList == null) {
return 0;
} else {
return (mArrayList.size());
}
}
@Override
public Object getItem(int position) {
if (mArrayList == null) {
return null;
} else {
return mArrayList.get(position);
}
}
@Override
public long getItemId(int position) {
return position;
}
public Filter getFilter() {
if (mNameFilter == null) {
mNameFilter = new NameFilter();
}
return mNameFilter;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View itemView = null;
itemView = convertView;
ViewHolder viewHolder = null;
if (itemView == null) {
itemView = mLayoutInflater.inflate(R.layout.listviewitem, null);
viewHolder = new ViewHolder();
viewHolder.textView = (TextView) itemView.findViewById(R.id.textView);
itemView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) itemView.getTag();
}
if (mArrayList != null) {
if (viewHolder.textView != null) {
viewHolder.textView.setText((mArrayList.get(position)));
}
}
convertView = itemView;
return convertView;
}
private class ViewHolder {
TextView textView;
}
//过滤数据
class NameFilter extends Filter {
//执行筛选
@Override
protected FilterResults performFiltering(CharSequence charSequence) {
FilterResults filterResults = new FilterResults();
for (Iterator<String> iterator = mArrayList.iterator(); iterator.hasNext();) {
String name = iterator.next();
System.out.println("---> name=" + name);
if (name.contains(charSequence)) {
mFilteredArrayList.add(name);
}
}
filterResults.values = mFilteredArrayList;
return filterResults;
}
//筛选结果
@Override
protected void publishResults(CharSequence arg0, FilterResults results) {
mArrayList = (List<String>) results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ListView
android:id="@+id/listView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="50dip"
android:gravity="center"
/>
</LinearLayout>