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();