效果图展示:
实现的效果:
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 keywordsList = new ArrayList();
private MyAdapter adapter;
private List findAllList = new ArrayList();
private HistoryDao dao;
@Override
public void getData() {
// 访问网络获取数据:热门搜索
new AsyncTask() {
@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();