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

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

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

1.RecyclerView的简单操作

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

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

废话不多说,先上效果图

android 利用数据库实现历史搜索记录功能_第1张图片


先看看工程界面截图

android 利用数据库实现历史搜索记录功能_第2张图片

其中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,管理历史纪录)