1. 程式人生 > >GreenDao+SearchView+FlowLoyout實現搜尋歷史和熱門搜尋

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語句,處理速度比sqlLite快兩倍以上,在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,將感之不盡!