Android搜索过滤

本文介绍了Android中实现搜索过滤的两种方式,重点讲解了利用Filterable接口和CursorAdapter进行异步搜索的过程。通过CursorFilter和CursorFilterClient,将搜索操作移到后台线程,提高用户体验。同时提到了FilterQueryProvider接口的使用,以及如何设置和启动过滤机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、简介

一般来说,我们可以使用以下几种方式实现搜索:

1)暴力搜索——直接使用数据库提供的功能,每次都从数据库中读取搜索的结果,存进一个数据结构用于Adapter显示,调用notifyDataSetChanged()刷新数据;

2)利用filter进行搜索。这块涉及到Filterable接口。推荐文章:Android实现Filterable通过输入文本框实现联系人自动筛选。有两点值得注意:a)Android原生组件AutoCompleteTextview就是使用该方法实现的;b)这个方法本质上还是调用notifyDataSetChanged()方法,并且还是要自己去实现搜索部分,只是整个方法看上去比较优雅,而且不用再去搜索数据库,最重要的一点是这个时候搜索过程被自动移到另外一个线程之中,搜索完毕之后才会刷新UI;

 二、Android做了哪些?
    1、为了实现数据的过滤,andorid设计了抽象类Filter,进行异步和同步的数据过滤操作。
    2、在Adapter中继承Filterable,提供给使用者Filter,进行过滤。
    3、在不同的View中,获得查询约束字符串,传递给Adapter,并且提供配合数据过滤的界面支持。
 三、Filter类
    Filter的使用流程如下:
    调用filter方法 ->在另一线程中调用performFiltering进行数据查询->得到数据过滤结果后调用publishResults将结果返回到使用它的客户端。
    该类中的performFiltering和publishResults均为抽象方法,需要继承者自己重写。
比如我们可以自定义一个Filter类实现performFiltering和publishResults方法就可以实现过滤了。

CursorFilter类就是Filter类的继承。CursorFilter在performFiltering中并没有直接进行数据的过滤,而是加入了CursorFilterClient成员,将过滤的操作转让给了CursorFilterClient,实际上CursorAdpater就是继承了CursorFilterClient接口,也就是说过滤操作实际上是在CursorAdapter中执行的。   

CursorAdapter实现Filterable接口实现了下面的方法

 public Filter getFilter() {
        if (mCursorFilter == null) {
            mCursorFilter = new CursorFilter(this);
        }
        return mCursorFilter;
    }

看一下CursorFilter的实现,实现Filter的两个抽象方法

class CursorFilter extends Filter {
    CursorFilterClient mClient;

    CursorFilter(CursorFilterClient client) {
        mClient = client;
    }

@Override
    protected FilterResults performFiltering(CharSequence constraint) {

        Cursor cursor = mClient.runQueryOnBackgroundThread(constraint);
        FilterResults results = new FilterResults();
        if (cursor != null) {
            results.count = cursor.getCount();
            results.values = cursor;
        } else {
            results.count = 0;
            results.values = null;
        }
        return results;
    }

    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        Cursor oldCursor = mClient.getCursor();
        if (results.values != null && results.values != oldCursor) {
            mClient.changeCursor((Cursor) results.values);
        }
    }

查询工作交给了CursorFilterClient这个类,而CursorAdapter实现了这个接口,所以

Cursor cursor = mClient.runQueryOnBackgroundThread(constraint);

这个方法是在CursorAdapter中实现的,我们看下

    public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
        if (mFilterQueryProvider != null) {
            return mFilterQueryProvider.runQuery(constraint);
        }
        return mCursor;
    }

其中的mFilterQueryProvider需要我设置一下

    public void setFilterQueryProvider(FilterQueryProvider filterQueryProvider) {
        mFilterQueryProvider = filterQueryProvider;
    }

看一下FilterQueryProvider这个接口,只有一个抽象方法

public interface FilterQueryProvider {
    Cursor runQuery(CharSequence constraint);
}

所以我们需要在外面继承这个接口实现它,并且实现runQuery方法中的查询搜索。

然后通过CursorAdapter的setFilterQueryProvider方法设置,之后整个机制完全串联起来,在外调用adapter.getFilter().filter(et_filter.getText().toString());  即可启动整个过滤机制。

整个机制实际上是用异步查询然后显示的流程,主要的流程处理在Filter的类中。下篇文章分析下Filter的具体实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值