GreenDao+SearchView+FlowLoyout实现搜索历史和热门搜索

之前写过一个静态的搜索页
FlowLayout流式布局实现标签、类似热门搜索这种效果
只是能实现界面效果,但是往往开发中是要把搜索历史缓存到本地数据库中,所以在原基础上添加了数据库功能。

并且把搜索框换成了SearchView,热门搜索标签还用洪洋大神的FlowLayout,请看布局


页面总共分为五部分,分别是搜索框,搜索按钮,热门搜索,搜索历史,和清空。

对于整个页面来说,热门搜索是比较简单的一部分,根据后台返回的数组或者集合,直接放上去就行。

重点在与搜索历史
其中要实现的功能
1、加载页面的时候请求数据库,获取所有的搜索历史,List倒序排列
2、点击搜索的时候,将搜索的关键字添加进数据库,刷新UI
3、清空搜索历史,清空数据库,刷新UI
4、搜索历史数量限制在一定范围,并且保证关键字不重复
5、实现标签的监听

关于

由于第一次使用GreenDao,中间遇到了一些问题,挖了一些坑。不过都解决了,其中要感谢简书上的两位作者给我的帮助@作者黄海佳、@作者 tonycheng93

关于界面所用到的库:

//FlowLayout
compile 'com.zhy:flowlayout-lib:1.0.3'
compile 'org.greenrobot:greendao:3.2.0'

关于GreenDao的优点:不需要写sql语句,处理速度比SQLite快两倍以上,在Android中用的很多的一个ORM框架。

如果还没有学习过的可以在简书搜相关教程文章有很多。

在引入GreenDao的时候如果遇到一直下载不下来,去改代理方式,就能解决。

FlowLayout是洪洋封装的一个开源布局框架,支持单选、多选等,适合用于产品标签等。对于像热门搜索,搜索历史,标签等这种布局的开发,是最合适不过的了。

一、初始化数据

在Make Modle的时候,会生成一个操作数据库的类,以Dao为结尾,我这里创建的modle是User,所以生成了一个UserDao类。

在进入界面的时候需要我们进行初始化数据库的方法

   /*初始化数据库相关*/
    private void initDbHelp() {
        DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "recluse-db", null);
        SQLiteDatabase db = helper.getWritableDatabase();
        DaoMaster daoMaster = new DaoMaster(db);
        DaoSession daoSession = daoMaster.newSession();
        userDao = daoSession.getUserDao();
    }

然后是获取数据
这里的获取数据是利用userDao查询数据库里所有存在的数据,当存在的时候,把清空历史搜索的按钮设置显示,无数据的布局设置为none。

由于结果默认升序排列,这里要使用Collections.reverse方法将其转为倒序,也就是最后搜索的关键词置顶。

这里把初始化的方法单独使用了一个类,方便后面其他操作也能调用。

    /**
     * 初始化adapter,更新list,重新加载列表
     */
    private void updateList() {
        //查询所有
        list = userDao.queryBuilder().list();
        //这里用于判断是否有数据
        if (list.size()==0){
            searchGreendaoRl.setVisibility(View.VISIBLE);
            searchGreendaoDelete.setVisibility(View.GONE);
        }else {
            searchGreendaoRl.setVisibility(View.GONE);
            searchGreendaoDelete.setVisibility(View.VISIBLE);
        }
        //list倒序排列
        Collections.reverse(list);
        adapter = new SearchViewGreenDaoAdapter(mContext, list);
        searchGreendaoLv.setAdapter(adapter);
        adapter.notifyDataSetChanged();

    }

二、搜索功能实现

搜索功能包括两个操作,一是跳转到搜索结果页,二是保存历史记录到本地数据库。

保存数据库,用到插入的方法,当输入一条关键字,在键盘点击回车搜索,或者在界面上点击搜索按钮,其执行的方法都是一样的。都是获取输入框文字,然后再保存。

SearchView中不再使用gittext来获取输入框的文字,要想获取文字,要实现其监听方法

 //搜索文本监听
        searchview.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            //点击搜索
            public boolean onQueryTextSubmit(String query) {
                name = query;
                Log.e("name--------", name + "");
                insertDB();
                return false;
            }

            @Override
            //当搜索内容改变
            public boolean onQueryTextChange(String newText) {
                name = newText;
                Log.e("newText---------", newText);
                if (name.equals("")) {
                    searchGreendaoLv.setFilterText(name);
                } else {
//                    insertDB();
                    searchGreendaoLv.clearTextFilter();
                }
                return false;
            }
        });

正常的获取文字只需要在onQueryTextSubmit方法把query的值返回,就能获取到输入的文字。
onQueryTextChange是用来动态获取输入的文字,常用在联想词等。

获取到我们的搜索关键字之后,
直接使用

userDao.insert(new User(null, name));

就可以添加到数据库,但是在这里为了开发需要,我做了以下限制。

1、保证历史记录一直只有8条记录
2、对于重复的历史记录,只保存最近的一条,如果有重复的,删除之前的。
3、当记录超过8条时,自动删除最下面的数据,实现循环。

 //增
    private void insertDB() {
        try {
            if (list.size() < 8) {
                //删除已经存在重复的搜索历史
                List<User> list2 = userDao.queryBuilder()
                        .where(UserDao.Properties.Name.eq(name)).build().list();
                userDao.deleteInTx(list2);
                //添加
                userDao.insert(new User(null, name));
                Toast.makeText(mContext, "插入数据成功:" + name, Toast.LENGTH_SHORT).show();
            } else {
                //删除第一条数据,用于替换最后一条搜索
                userDao.delete(userDao.queryBuilder().list().get(0));
                //删除已经存在重复的搜索历史
                List<User> list3 = userDao.queryBuilder()
                        .where(UserDao.Properties.Name.eq(name)).build().list();
                userDao.deleteInTx(list3);
                //添加
                userDao.insert(new User(null, name));
            }
            updateList();
        } catch (Exception e) {
            Toast.makeText(mContext, "插入失败", Toast.LENGTH_SHORT).show();
        }

    }

在添加完成之后,使用之前定义的初始化方法刷新UI.

三、清空数据库

这一步是比较简单的,直接调用deleteAll就能删除所有的数据,然后顺便清空list,刷新Adapter,布局改变。

  //清空数据库
    private void delectAllDB() {
        try {
            userDao.deleteAll();
            list.clear();
            adapter.notifyDataSetChanged();
            searchGreendaoRl.setVisibility(View.VISIBLE);
            searchGreendaoDelete.setVisibility(View.GONE);
            Toast.makeText(mContext, "清空数据库", Toast.LENGTH_SHORT).show();
        } catch (Exception e) {
            Log.e("exception-----delete", user + "message:" + e.getMessage() + "");
        }
    }

四、热门标签流式布局效果

在引入FlowLoyout后,Activity里可以自己定义一个数组

private String[] mVals = new String[]
            {"Hello", "Android", "Weclome Hi ", "Button", "TextView", "Hello",
                    "Android", "Weclome", "Button ImageView", "TextView", "Helloworld"};

或者从后台获取json都可以,

然后在setAdapter中把数据传入。

searchGreendaoFlowlayout.setAdapter(new TagAdapter<String>(names) {
            @Override
            public View getView(FlowLayout parent, int position, final String s) {
                final TextView tv = (TextView) LayoutInflater.from(mContext).inflate(
                        R.layout.search_page_flowlayout_tv, searchGreendaoFlowlayout, false);
                tv.setText(s);
                tv.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(mContext, "" + s, Toast.LENGTH_SHORT).show();

                    }
                });
                return tv;
            }
        });

顺便把热门标签的监听也写上了。

如果是要对历史搜索的列表监听,直接在Adapter中调用onclickListener就可以了。


其实关于搜索,并没有太难的地方,主要是考察对数据库的一些基本操作,把刚学习的GreenDao应用到项目中来。

还有很多地方还需要进一步优化。

本来想再加个联想词的功能,但是在一个只有8条记录的历史上使用,有点不适合。
联想词多用于大量的数据列表的时候,方便用户进行筛选。
从产品角度来说是不合理的,我们在开发的同时也不得不考虑功能的合理性。

项目源码在GitHub
如果你觉得还不错,欢迎Star,将感之不尽!


相关阅读资料
Android ORM框架学习-greenDAO的基本使用
GreenDAO 3.x项目开发实战持续更新ing — Android ORM框架(三)
SearchView+RecyclerView+GreenDao的搜索功能实现(2)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容