SearchView+RecyclerView+GreenDao的搜索功能实现(1)

功能需求如下:

①后端商品搜索会有热搜和联想词库两种类型提供

②联想词库可以包含热搜和搜索历史

③根据词库版本号是否变更数据库更新数据库存储的词库,搜索记录不会删除

④热词和联想词库根据被搜索过的次数排序,搜索历史根据搜索的时间排序

⑤输入词联想匹配的时候,搜索历史按搜索时间优先排在前面,搜索词库匹配按被搜索次数排在后面

⑥打开搜索框未输入任何词,或者输入词后又清空,无搜索历史时,只显示搜索热词;有搜索历史,优先显示搜索历史,搜索历史有删除按钮

⑦会有标题标注搜索历史和热搜

表设计如下

字段 说明
keyword 单词名称,不可为空
count 搜索次数,用于热词和联想词排序
time 搜索时间,用于搜索历史排序
type 单词的类型(历史,热词,联想词库),不可为空

GreenDao的使用

使用参考的是greenDAO简单使用经验

GreenDao特点

最大性能(最快的 Android ORM)
易于使用API
高度优化
最小内存消耗
api接口可以直接通过对象类进行建表、增删改查等

使用步骤

①在原项目中新建一Java的Module取名为daogenerator,用于生成数据库操作所需的Dao类

SearchView+RecyclerView+GreenDao的搜索功能实现(1)_第1张图片

build.gradle加入如下依赖

SearchView+RecyclerView+GreenDao的搜索功能实现(1)_第2张图片

创建一个GreenDaoGenerator类用于生成所需的表格和字段

public class GreenDaoGenerator {

    public static void main(String[] args) throws Exception {
        int version = 1;
        String defaultJavaPackage = "com.sailvan.dealsale.greendao";
        // 第一个参数用来更新数据库版本号,第二个参数为要生成的DAO类所在包路径
        Schema schema = new Schema(version, defaultJavaPackage);
        // 生成表
        addTable(schema);
        // 第一个参数是Schema对象,第二个参数是希望自动生成的代码对应的项目路径
        new DaoGenerator().generateAll(schema, "./demo/src/main/java-gen");
    }

    private static void addTable(Schema schema) {
        // Entity表示一个实体可以对应成数据库中的表,这里表名就是SearchKeywordsTable
        Entity note = schema.addEntity("SearchKeywordsTable");
        // 添加ID字段
        note.addIdProperty();
        // 添加keyword字段,不允许为空
        note.addStringProperty("keyword").notNull();
        // 添加搜索次数字段
        note.addLongProperty("count");
        // 添加搜索时间字段
        note.addLongProperty("time");
        // 添加类型字段不允许为空
        note.addIntProperty("type").notNull();
    }

}

DaoGenerator().generateAll(schema, “./demo/src/main/java-gen”);第二个参数是希望自动生成的代码对应的项目路径,demo项目和java项目daogenerator处于同一级目录,注意的是java-gen必须手动创建
SearchView+RecyclerView+GreenDao的搜索功能实现(1)_第3张图片

运行GreenDaoGenerator 代码成功后生成DaoMaster、DaoSession、SearchkeywordTable、SearchkeywordTableDao四个文件

②demo项目使用GreenDao的api完成CRUD

build.gradle加入如下依赖

SearchView+RecyclerView+GreenDao的搜索功能实现(1)_第4张图片

CRUD的实现方法如下:

Bean如下

public class SearchKeywords {

        public String keyword;
        public long value;
        public long time;
        public int type;

    public SearchKeywords(String keyword, long value, long time, int type) {
        this.keyword = keyword;
        this.value = value;
        this.time = time;
        this.type = type;
    }
}

方法如下

    private SearchKeywordsTableDao mKeywordsTableDao;

    private Activity mContext = this;

    /** * 获取数据库操作对象 * ①先创建了一个SQLiteOpenHelper并创建连接到一个具体数据库 * ②再根据具体的datebase创建一个master对象用于session * ③最后通过master创建一个数据库的会话操作 * * @param tableDao 数据库dao * @return 数据库dao,通常对应具体的java类,其有更多的权限和方法来操作数据库元素。 */
    private SearchKeywordsTableDao getSearchKeywordsTableDao(SearchKeywordsTableDao tableDao) {
        if (tableDao != null) return tableDao;
        DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(mContext, Constant.DB_NAME, null);
        SQLiteDatabase db = helper.getWritableDatabase();
        // 保存了sqlitedatebase对象以及操作DAO classes(注意:不是对象)。其提供了一些创建和删除table的静态方法,其内部类OpenHelper和DevOpenHelper实现了SQLiteOpenHelper并创建数据库的框架。
        DaoMaster daoMaster = new DaoMaster(db);
        // 会话层。操作具体的DAO对象(注意:是对象),比如各种getter方法
        DaoSession daoSession = daoMaster.newSession();
        return daoSession.getSearchKeywordsTableDao();
    }

    /** * 数据库插入搜索数据 * * @param keywords 搜索词名称list */
    private void insertSearchKeywordsToDb(List<SearchKeywords> keywords) {
        for (SearchKeywords info : keywords) {
            SearchKeywordsTable keywordsTable = new SearchKeywordsTable(null,           
            info.keyword, info.value, info.time, info.type);
            mKeywordsTableDao.insertOrReplace(keywordsTable);
        }
    }

    /** * 插入历史纪录到数据库 * * @param info 搜索的单词 */
    private void insertHistorySearchKeywordsToDb(SearchKeywords info) {
        // 数据库存在此历史时删除之
        clearSearchKeyWords(info.keyword);
        // 然后再插入
        SearchKeywordsTable keywordsTable = new SearchKeywordsTable(null, 
        info.keyword, info.value, info.time, info.type);
        mKeywordsTableDao.insertOrReplace(keywordsTable);
    }

    /** * 根据搜索类型查找数据,放到list,用于填充RecycleView * * @param searchList list * @param type 搜索类型(历史、热搜、联想词) * @return 搜索的结果集合 */
    private List<SearchKeywordsTable> insertKeywordsToRecyclerView(ArrayList<String> 
    searchList, int type) {
        QueryBuilder<SearchKeywordsTable> qb = mKeywordsTableDao.queryBuilder();
        qb.where(SearchKeywordsTableDao.Properties.Type.eq(type));
        // 热搜根据搜索数排序,历史根据搜索时间排
        qb.orderDesc(type == Constant.SEARCH_KEYWORDS_HOT ?  
        SearchKeywordsTableDao.Properties.Count : 
        SearchKeywordsTableDao.Properties.Time);
        List<SearchKeywordsTable> tables = qb.list();
        for (SearchKeywordsTable table : tables) {
            searchList.add(table.getKeyword());
        }
        return tables;
    }

    /** * 根据输入的词查找数据库匹配的数据,放到list中,用于填充RecycleView * 用于输入单词的时候联想匹配单词 * ①首先匹配历史,排序按搜索的时间 * ②然后匹配联想词库,排序按搜索的次数,如果词库包含搜索历史,则不匹配因为第一步已经匹配 * * @param hotSearchList list * @param word 输入单词 * @return 搜索的结果集合 */
    private List<SearchKeywordsTable> insertMatchKeywordsToRecycleView(ArrayList<String> hotSearchList, String word) {
        // 先查找历史,按时间排序
        List<SearchKeywordsTable> tables = mKeywordsTableDao.queryBuilder()
                .where(SearchKeywordsTableDao.Properties.Keyword.like("%" + word + "%"),
                      SearchKeywordsTableDao.Properties.Type.eq(Constant.SEARCH_KEYWORDS_HISTORY))
                .orderDesc(SearchKeywordsTableDao.Properties.Time)
                .list();
        for (SearchKeywordsTable table : tables) {
            hotSearchList.add(table.getKeyword());
            DebugLog.e("查找历史有匹配");
        }
        // 然后查找词库,按次数排序
        List<SearchKeywordsTable> tables1 = mKeywordsTableDao.queryBuilder()
                .where(SearchKeywordsTableDao.Properties.Keyword.like("%" + word + "%"),
                        // 热词不包括在联想里面,因为联想里面会包含热词
                SearchKeywordsTableDao.Properties.Type.eq(Constant.SEARCH_KEYWORDS_ALL))
                .orderDesc(SearchKeywordsTableDao.Properties.Count)
                .list();
        for (SearchKeywordsTable table : tables1) {
            // 没跟历史词重复才添加上去
            if (!hotSearchList.contains(table.getKeyword())) {
                DebugLog.e("查找词库有匹配,且不跟历史重复");
                hotSearchList.add(table.getKeyword());
            }
        }
        return tables;
    }


    /** * 数据库清除某个搜索历史 */
    private void clearSearchKeyWords(String keyword) {
        DeleteQuery<SearchKeywordsTable> dq = mKeywordsTableDao.queryBuilder()
                .where(SearchKeywordsTableDao.Properties.Keyword.eq(keyword), SearchKeywordsTableDao.Properties.Type.eq(Constant.SEARCH_KEYWORDS_HISTORY))
                .buildDelete();
        dq.executeDeleteWithoutDetachingEntities();
    }

    /** * 数据库清空搜索历史以外的数据 */
    private void clearTopAndAssociativeSearchKeyWords() {
        // 将不是历史的清空掉
        mKeywordsTableDao = getSearchKeywordsTableDao(mKeywordsTableDao);
        DeleteQuery<SearchKeywordsTable> dq = mKeywordsTableDao.queryBuilder()
                .where(SearchKeywordsTableDao.Properties.Type.notEq(Constant.SEARCH_KEYWORDS_HISTORY))
                .buildDelete();
        dq.executeDeleteWithoutDetachingEntities();
    }

    /** * 数据库清空搜索历史的数据,用于一键情况历史纪录 */
    private void clearHisotySearchKeyWords() {
        // 将不是历史的清空掉
        mKeywordsTableDao = getSearchKeywordsTableDao(mKeywordsTableDao);
        DeleteQuery<SearchKeywordsTable> dq = mKeywordsTableDao.queryBuilder()
        .where(SearchKeywordsTableDao.Properties.Type.eq(Constant.SEARCH_KEYWORDS_HISTORY))
        .buildDelete();
        dq.executeDeleteWithoutDetachingEntities();
    }

你可能感兴趣的:(android,数据库,排序,联想,greenDAO)