android|android 利用数据库实现历史搜索记录功能

最近在一个项目中使用到了搜索功能,特来此记录一下
本篇博文需要用到的知识点: 1.RecyclerView的简单操作
2.本地数据库的简单操作
3.ScrollView与RecyclerView的滑动冲突解决
废话不多说,先上效果图
android|android 利用数据库实现历史搜索记录功能
文章图片



先看看工程界面截图
android|android 利用数据库实现历史搜索记录功能
文章图片


其中HistorySearchAdapter是历史记录的适配器,HistorySearchUtil是本地数据库的管理工具类
1.


这个大概看看就好,可以根据自己的喜好设计
2.history_search_item.xml历史纪录RecyclerView的单项视图


3.数据库管理工具类HistorySearchUtil.java

public class HistorySearchUtil {/** * 建表语句 */ private static final String CREATE_HISTORY_SEARCH = "create table searchHistory (" + "id integer primary key autoincrement, " + "name text)"; private final String TAG = "HistorySearchUtil"; private final String TABLE_NAME = "searchHistory"; public Context mContext; private static HistorySearchUtil mHistorySearchUtil; private MyDatabaseHelper mMyDatabaseHelper; private HistorySearchUtil(Context context) { mMyDatabaseHelper = new MyDatabaseHelper(context, "Record.db", null, 1); this.mContext = context; }public static HistorySearchUtil getInstance(Context context) {//得到一个实例 if (mHistorySearchUtil == null) { mHistorySearchUtil = new HistorySearchUtil(context); } else if ((!mHistorySearchUtil.mContext.getClass() .equals(context.getClass()))) {判断两个context是否相同 mHistorySearchUtil = new HistorySearchUtil(context); } return mHistorySearchUtil; }/** * 添加一条新纪录 * @param name */ public void putNewSearch(String name) { SQLiteDatabase db = mMyDatabaseHelper.getWritableDatabase(); if (!isExist(name)) {//判断新纪录是否存在,不存在则添加 ContentValues values = new ContentValues(); values.put("name", name); db.insert(TABLE_NAME, null, values); } }/** * 判断记录是否存在 * @param name * @return */ public boolean isExist(String name) { SQLiteDatabase db = mMyDatabaseHelper.getWritableDatabase(); Cursor cursor = db.rawQuery("select * from " + TABLE_NAME + " where name = ?", new String[]{name}); if (cursor.moveToFirst()) {//如果存在 return true; } else { return false; } }/** * 查询所有历史纪录 * @return */ public List queryHistorySearchList() { SQLiteDatabase db = mMyDatabaseHelper.getWritableDatabase(); List list = new ArrayList(); Cursor cursor = db.query(TABLE_NAME, null, null, null, null, null, null); if (cursor.moveToFirst()) { do { String name = cursor.getString(cursor.getColumnIndex("name")); list.add(name); } while(cursor.moveToNext()); } return list; }/** * 删除单条记录 * @param name */ public void deleteHistorySearch(String name) { SQLiteDatabase db = mMyDatabaseHelper.getWritableDatabase(); if (isExist(name)) { db.delete(TABLE_NAME, "name = " + "'" + name + "'", null); } }/** * 删除所有记录 */ public void deleteAllHistorySearch() { SQLiteDatabase db = mMyDatabaseHelper.getWritableDatabase(); db.delete(TABLE_NAME, null, null); }public class MyDatabaseHelper extends SQLiteOpenHelper {public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factoty, int version) { super(context, name, factoty, version); }@Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_HISTORY_SEARCH); //建表 }@Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {} } }

其中操作比较简单,根据注释基本都能看懂
4.主界面操作MainActivity.java

package zzx.historysearch; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import java.util.ArrayList; import adapter.HistorySearchAdapter; import util.HistorySearchUtil; public class MainActivity extends AppCompatActivity {private EditText searchEdit; //搜索EditText private TextView searchTv; //搜索按钮,不过是以TextView形式 private RecyclerView histotyRecycler; //历史纪录列表 private TextView historyEmptyTv; //清空历史纪录按钮 private LinearLayout histotySearchLayout; //历史记录整个布局private HistorySearchAdapter adapter; //适配器private ArrayList histotyList = new ArrayList(); //历史纪录数组@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); android.support.v7.app.ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.hide(); } initViews(); //初始化组件 initHistoryRecycler(); //初始化historyRecyclerView getHistoryList(); //得到历史记录数组 setSearchTvListener(); //设置搜索按钮监听器 setHistoryEmptyTvListener(); //设置清空记录按钮监听器 }private void setHistoryEmptyTvListener() { historyEmptyTv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { HistorySearchUtil.getInstance(MainActivity.this) .deleteAllHistorySearch(); getHistoryList(); adapter.notifyDataSetChanged(); //刷新列表 showViews(); } }); }private void setSearchTvListener() { searchTv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { HistorySearchUtil.getInstance(MainActivity.this) .putNewSearch(searchEdit.getText().toString()); //保存记录到数据库 getHistoryList(); adapter.notifyDataSetChanged(); showViews(); Toast.makeText(MainActivity.this, "此条记录已保存到数据库", Toast.LENGTH_SHORT).show(); } }); }/** * 设置历史记录界面可见性,即记录为空时,不显示清空历史记录按钮等view */ private void showViews() { if (histotyList.size() > 0) { histotySearchLayout.setVisibility(View.VISIBLE); } else { histotySearchLayout.setVisibility(View.GONE); } }private void initHistoryRecycler() { LinearLayoutManager layoutManager = new LinearLayoutManager(this); layoutManager.setOrientation(LinearLayoutManager.VERTICAL); histotyRecycler.setLayoutManager(layoutManager); histotyRecycler.setNestedScrollingEnabled(false); //解决滑动冲突 adapter = new HistorySearchAdapter(this, histotyList); histotyRecycler.setAdapter(adapter); adapter.setOnItemClickListener(new HistorySearchAdapter.OnItemClickListener() { @Override public void onItemNameTvClick(View v, String name) { searchEdit.setText(name); }@Override public void onItemDeleteImgClick(View v, String name) { HistorySearchUtil.getInstance(MainActivity.this) .deleteHistorySearch(name); getHistoryList(); adapter.notifyDataSetChanged(); showViews(); } }); }private void initViews() { searchEdit = (EditText) findViewById(R.id.search_edit); searchTv = (TextView) findViewById(R.id.search_tv); historyEmptyTv = (TextView) findViewById(R.id.history_empty_tv); histotyRecycler = (RecyclerView) findViewById(R.id.history_search_recycler); histotySearchLayout = (LinearLayout) findViewById(R.id.history_search_layout); }private void getHistoryList() { histotyList.clear(); histotyList.addAll(HistorySearchUtil.getInstance(this) .queryHistorySearchList()); adapter.notifyDataSetChanged(); showViews(); } }


根据注释,应该都能看懂,值得注意的是。在本篇中解决ScrollView与RecyclerView的冲突的办法是,将ScrollView换成NestedScrollView,大家可以看看main_activity.xml里验证一下,然后在设置RecyclerView时将setNestedScrollingEnabled设置为false就可以了,即上文中的
histotyRecycler.setNestedScrollingEnabled(false);

至于NestedScrollView的其他用法,大家可以自行百度或者谷歌,这里就不展开了。
5.RecyclerView适配器HistorySearchAdapter.java

public class HistorySearchAdapter extends Adapter implements View.OnClickListener {private Context mContext; private OnItemClickListener mOnItemClickListener; //item点击监听接口private List histotyList = new ArrayList(); public HistorySearchAdapter(Context context, List histotyList) { this.mContext = context; this.histotyList = histotyList; }class ViewHolder extends RecyclerView.ViewHolder {private TextView nameTv; private ImageView deleteImg; private View itemView; public ViewHolder(View itemView) { super(itemView); nameTv = (TextView) itemView.findViewById(R.id.search_history_item_tv); deleteImg = (ImageView) itemView.findViewById(R.id.search_history_item_img); this.itemView = itemView; } }@Override public HistorySearchAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {View view = LayoutInflater.from(mContext) .inflate(R.layout.history_search_item, null); ViewHolder holder = new ViewHolder(view); return holder; }@Override public void onBindViewHolder(HistorySearchAdapter.ViewHolder holder, int position) { holder.nameTv.setText(histotyList.get(position)); holder.nameTv.setTag(histotyList.get(position)); holder.deleteImg.setTag(histotyList.get(position)); holder.nameTv.setOnClickListener(this); holder.deleteImg.setOnClickListener(this); }public void onClick(View v) { switch (v.getId()) { case R.id.search_history_item_tv://点击历史纪录名称时调用 if (mOnItemClickListener != null) { mOnItemClickListener.onItemNameTvClick(v, (String) v.getTag()); } break; case R.id.search_history_item_img://点击删除按钮时调用 if (mOnItemClickListener != null) { mOnItemClickListener.onItemDeleteImgClick(v, (String) v.getTag()); } break; default: } }/** * 设置item点击监听器 * @param listener */ public void setOnItemClickListener(OnItemClickListener listener) { this.mOnItemClickListener = listener; }@Override public int getItemCount() { return histotyList.size(); }/** * item点击接口 */ public interface OnItemClickListener { void onItemNameTvClick(View v, String name); //点击历史纪录名称时 void onItemDeleteImgClick(View v, String name); //点击删除按钮时 } }


在本适配器中采用了观察者模式,也是大众常用的一种模式,将删除按钮和历史纪录TextView的点击事件处理,交给了OnItemClickListener来处理,这样的话在MainActivity中可以很好的处理相关数据,也是代码更加规范吧。
好了,本篇博文到此也就结束了。至于item中使用的删除图片大家可以在阿里矢量库中寻找,里面非常多。
【android|android 利用数据库实现历史搜索记录功能】

    推荐阅读