1. 程式人生 > >Android之搜尋功能的實現

Android之搜尋功能的實現

效果圖展示:
這裡寫圖片描述
實現的效果:
1.熱門商品搜尋欄中的資料從網路介面獲取
2.搜尋歷史商品中的資料從SQLite資料庫中獲取
3.當點選熱門商品搜尋的時候,該資料會立刻出現在搜尋歷史商品中,不會重複增加已經出現過的商品,歷史中的商品按照最新時間排序。
4.效果圖中的button沒有做監聽,其實現原理是:獲取EditText中的內容,按照服務端的介面格式要求,傳送get請求,訪問服務端獲取相應的資料。
5.搜尋歷史商品欄的展示資料比較長是由於在bean中對toString 方法做了以下的重寫。直接return hotword 也是可以的。

@Override
    public
String toString() { return "SearchDBData [hotword=" + hotword + "]"; }

重要知識點:
1.AsyncTask 的使用:
2.json資料解析:
3.ExpandableListView的使用:
4.表的設計和SQLiteDatabase的增刪查改操作:

先貼上程式碼,後面再對一些重要的程式碼做解釋說明:

public class SearchFragment extends BaseFragment {

    private ExpandableListView mExpandableListView;
    private
EditText inputEditText; private Button searchButton; private SearchRecommendData recommendData; private ArrayList<String> keywordsList = new ArrayList<String>(); private MyAdapter adapter; private List<SearchDBData> findAllList = new ArrayList<SearchDBData>(); private
HistoryDao dao; @Override public void getData() { // 訪問網路獲取資料:熱門搜尋 new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { String url = "http://xxxxxxxxxxxxxxx"; String json = HttpUtil.get(url, "utf-8"); // recommendData = JSON.parseObject(json, // SearchRecommendData.class); Gson gson = new Gson(); recommendData = gson.fromJson(json, SearchRecommendData.class); keywordsList = recommendData.search_keywords; // 訪問資料庫獲取歷史記錄 findAllList = dao.findAll(); return null; }; protected void onPostExecute(Void result) { if (adapter == null) { adapter = new MyAdapter(); mExpandableListView.setAdapter(adapter); } else { adapter.notifyDataSetChanged(); } }; }.execute(); } @Override public int getLayoutId() { return R.layout.fragment_search; } @Override public void initView() { dao = new HistoryDao(mContext); // 查詢fragment中控制元件 mExpandableListView = (ExpandableListView) rootView .findViewById(R.id.elv_search); inputEditText = (EditText) rootView .findViewById(R.id.et_input_searchfragment); searchButton = (Button) rootView.findViewById(R.id.btn_searchfragment); mExpandableListView.setGroupIndicator(null); // 對mExpandableListView設定監聽事件: MyonChildClickListener childListener = new MyonChildClickListener(); mExpandableListView.setOnChildClickListener(childListener); } private class MyonChildClickListener implements OnChildClickListener { @Override public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { // Toast.makeText(mContext, keywordsList.get(childPosition), // 0).show(); // String inputStr = inputEditText.getText().toString(); String hotword = keywordsList.get(childPosition); // ContentValues values = new ContentValues(); // values.put("hotword", hotword); // values.put("updatetime",System.currentTimeMillis()); // dao.add(values); dao.addOrUpdate(hotword); findAllList.clear(); findAllList = dao.findAll(); adapter.notifyDataSetChanged(); return true;// 自己處理事情 } } private class MyAdapter extends BaseExpandableListAdapter { @Override public int getGroupCount() { if (findAllList != null) { return 2; } else { return 1; } } @Override public int getChildrenCount(int groupPosition) { // 返回單一組中的數量 if (findAllList != null) { if (groupPosition == 0) { return keywordsList.size(); } else if (groupPosition == 1) { return findAllList.size(); } } return keywordsList.size(); } @Override public Object getGroup(int groupPosition) { if (groupPosition == 0) { return "熱門商品搜尋";// 初始化元件的時候用到: } else if (groupPosition == 1) { return "搜尋歷史商品"; } return null; } @Override public Object getChild(int groupPosition, int childPosition) { if (findAllList != null) { if (groupPosition == 0) { return keywordsList.get(childPosition); } else if (groupPosition == 1) { return findAllList.get(childPosition).toString(); } } return keywordsList.get(childPosition); } @Override public long getGroupId(int groupPosition) { // TODO Auto-generated method stub return 0; } @Override public long getChildId(int groupPosition, int childPosition) { // TODO Auto-generated method stub return 0; } @Override public boolean hasStableIds() { // TODO Auto-generated method stub return false; } @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { View view = View.inflate(mContext, R.layout.search_group, null); TextView groupnameTextView = (TextView) view .findViewById(R.id.tv_name_search); String name = (String) getGroup(groupPosition); groupnameTextView.setText(name); return view; } @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { String items = (String) getChild(groupPosition, childPosition); View view = View.inflate(mContext, R.layout.search_child, null); TextView childnameTextView = (TextView) view .findViewById(R.id.tv_childname_search); childnameTextView.setText(items); return view; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { // true:支援點選事件 return true; } } }

先說AsyncTask,由於個人習慣性將獲取資料的來源和展示資料寫在同一個activity或是fragment中,哪些資料有用,就將哪些資料設定為成員變數,不需要再傳遞資料了,這是寫在同一個類中的好處。
所以在用AsyncTask的時候可以看到傳遞的引數都是Void的。如果單獨將AsyncTask另外開闢一個類來寫的話,傳遞的引數又會有不同。

再說資料庫:根據實現效果中的第3點要求:搜尋過的商品不能重複,並且最新搜尋的放置在第一位,所以設計表的時候一定要帶上時間,時間的取值也就是System.currentTimeMillis();
資料庫中的關鍵程式碼如下:

public void addOrUpdate(String hotword){
        SQLiteDatabase db = helper.getWritableDatabase();
        String sql = "select id from t_words where hotword = ? ";
        Cursor cursor = db.rawQuery(sql, new String[]{hotword});
        if(cursor.getCount()>0){
            //說明資料庫中已經有資料:更新資料庫的時間:
            String sql_update = "update t_words set updatetime = ? where hotword = ? ";
            db.execSQL(sql_update, new String[]{System.currentTimeMillis()+"",hotword});
        }else{
            //直接插入一條記錄:
            String sql_add = "insert into t_words(hotword,updatetime) values (?,?);";
            db.execSQL(sql_add, new String[]{hotword,System.currentTimeMillis()+""});
        }

        cursor.close();
        db.close();
    }
public List<SearchDBData> findAll(){
        List<SearchDBData> data = new ArrayList<SearchDBData>();;
        SQLiteDatabase db = helper.getReadableDatabase();
        Cursor cursor = db.query("t_words", null, null, null, null, null, "updatetime desc");

        //遍歷遊標,將資料儲存在
        while(cursor.moveToNext()){
            SearchDBData searchDBData = new SearchDBData();
            searchDBData.id = cursor.getInt(cursor.getColumnIndex("id"));
            searchDBData.hotword = cursor.getString(cursor.getColumnIndex("hotword"));
            searchDBData.updatetime = cursor.getLong(cursor.getColumnIndex("updatetime"));
            data.add(searchDBData);
        }
        cursor.close();
        db.close();
        return data;
    }

另外:以下是點選事件中的程式碼,特別要注意2點:(1)往集合中增加資料的時候先清空下集合,避免資料越加越多(2)資料有變更的時候,需要notify下,保持介面的更新。

            dao.addOrUpdate(hotword);
            findAllList.clear();
            findAllList = dao.findAll();
            adapter.notifyDataSetChanged();