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

来源:互联网 发布:网络隐私权的法律规定 编辑:程序博客网 时间:2024/05/20 14:19

最近在一个项目中使用到了搜索功能,特来此记录一下

本篇博文需要用到的知识点:

1.RecyclerView的简单操作

2.本地数据库的简单操作

3.ScrollView与RecyclerView的滑动冲突解决

废话不多说,先上效果图


先看看工程界面截图


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

1.

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="zzx.historysearch.MainActivity"    android:orientation="vertical">    <LinearLayout        android:layout_width="match_parent"        android:layout_height="?attr/actionBarSize"        android:background="@color/colorPrimary"        android:orientation="horizontal"        android:paddingTop="4dp"        android:paddingLeft="6dp"        android:paddingRight="6dp"        android:paddingBottom="4dp">        <EditText            android:id="@+id/search_edit"            android:layout_width="0dp"            android:layout_weight="6"            android:layout_height="wrap_content"            android:hint="搜索"            android:textColor="#333333"            android:textColorHint="#dddddd"            android:textSize="15sp"/>        <TextView            android:id="@+id/search_tv"            android:layout_width="0dp"            android:layout_weight="1"            android:layout_height="wrap_content"            android:gravity="center"            android:text="搜索"            android:textSize="15sp"            android:textColor="#ffffff"            android:layout_centerVertical="true"            android:layout_marginLeft="6dp"/>    </LinearLayout>    <android.support.v4.widget.NestedScrollView        android:layout_width="match_parent"        android:layout_height="wrap_content">        <LinearLayout            android:id="@+id/history_search_layout"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:orientation="vertical">            <TextView                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:text="历史纪录"                android:textColor="#dddddd"                android:textSize="13sp"                android:paddingTop="8dp"                android:paddingLeft="8dp"                android:paddingBottom="8dp"/>            <View                android:layout_width="match_parent"                android:layout_height="1dp"                android:background="#dddddd"/>            <android.support.v7.widget.RecyclerView                android:id="@+id/history_search_recycler"                android:layout_width="match_parent"                android:layout_height="wrap_content">            </android.support.v7.widget.RecyclerView>            <TextView                android:id="@+id/history_empty_tv"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:text="清除所有历史记录"                android:textColor="#dddddd"                android:textSize="13sp"                android:paddingTop="8dp"                android:paddingBottom="8dp"                android:gravity="center"/>        </LinearLayout>    </android.support.v4.widget.NestedScrollView></LinearLayout>
这个大概看看就好,可以根据自己的喜好设计

2.history_search_item.xml历史纪录RecyclerView的单项视图

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical" android:layout_width="match_parent"    android:layout_height="match_parent">    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal">        <TextView            android:id="@+id/search_history_item_tv"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:paddingBottom="10dp"            android:paddingLeft="10dp"            android:paddingRight="4dp"            android:paddingTop="10dp"            android:textColor="#333333"            android:textSize="17sp" />        <ImageView            android:id="@+id/search_history_item_img"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentRight="true"            android:layout_centerVertical="true"            android:layout_marginRight="6dp"            android:src="@mipmap/ic_delete" />    </RelativeLayout></LinearLayout>
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<String> queryHistorySearchList() {        SQLiteDatabase db = mMyDatabaseHelper.getWritableDatabase();        List<String> list = new ArrayList<String>();        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<String> histotyList = new ArrayList<String>();//历史纪录数组    @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<HistorySearchAdapter.ViewHolder>                                implements View.OnClickListener {    private Context mContext;    private OnItemClickListener mOnItemClickListener;//item点击监听接口    private List<String> histotyList = new ArrayList<String>();    public HistorySearchAdapter(Context context, List<String> 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中使用的删除图片大家可以在阿里矢量库中寻找,里面非常多。


原创粉丝点击