搜索历史记录的实现-Android

2,252 阅读3分钟

小知识,大挑战!本文正在参与「程序员必备小知识」创作活动

本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。

前言

最近一个客户想要实现搜索中搜索历史的功能,其实这个功能听起来很简单,实际上里面有很多逻辑在里面,一开始写的时候脑子蒙蒙的,最后提给客户的时候一堆毛病,这一次来详细梳理一下,也分享一下我的思路

主要逻辑

  1. 搜索后保存当前内容
  2. 将最新的搜索记录在最前面
  3. 搜索历史记录可以点击并执行搜索功能,并将其提到最前面

我里面使用了ObjectBox作为数据存储,因为实际项目用的Java所以没用Room,而且Room好像第一次搜索至少要200ms,不过可以在某个activity随便搜索热启动一下.GreenDao使用有点麻烦,查询条件没有什么太大需求,直接用ObjectBox了,而且使用超级简单

Code

ObjectBox的工具类

public class ObjectBoxUtils {
    public static BoxStore init() {
        BoxStore boxStore = null;
        try {
            boxStore = MyApplication.getBoxStore();
            if (boxStore == null) {
                boxStore = MyObjectBox.builder().androidContext(MyApplication.applicationContext).build();
                MyApplication.setBoxStore(boxStore);
            }
        } catch (Exception e) {
        }
        return boxStore;
    }


    public static <T> List<T> getAllData(Class clazz) {
        try {
            BoxStore boxStore = init();
            if (boxStore != null && !boxStore.isClosed()) {
                Box<T> box = boxStore.boxFor(clazz);

                return box.getAll();
            }
        } catch (Exception e) {
        }
        return new ArrayList<>();
    }


    /**
     * 添加数据
     */
    public static <T> long addData(T o, Class c) {
        try {
            BoxStore boxStore = init();
            if (boxStore != null && !boxStore.isClosed()) {
                return boxStore.boxFor(c).put(o);
            }
        } catch (Throwable e) {
        }
        return  0;
    }


    public static HistoryBean getHistroyBean(String name) {
        try {
            BoxStore boxStore = init();
            if (boxStore != null && !boxStore.isClosed()) {
                Box<HistoryBean> box = boxStore.boxFor(HistoryBean.class);
                HistoryBean first = box.query().equal(HistoryBean_.name, name).build().findFirst();
                return first;
            }
        } catch (Exception e) {
        }
        return null;
    }
} 

其实我在Application就初始化了ObjectBox,但是实际项目中有时候会初始化失败,导致直接空指针,所有每次调用我都会判断一下是否初始化了,没有的话就进行相应操作

Activity

class HistoryActivity : AppCompatActivity() {
    private var list: MutableList<HistoryBean>? = null
    private var inflate: ActivityHistoryBinding? = null
    private var historyAdapter: HistoryAdapter? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        inflate = ActivityHistoryBinding.inflate(layoutInflater)
        setContentView(inflate?.root)
        list = ObjectBoxUtils.getAllData(HistoryBean::class.java)
        list?.sort()
        inflate!!.rv.layoutManager = LinearLayoutManager(this, RecyclerView.HORIZONTAL, false)
        historyAdapter = HistoryAdapter(this, list)
        inflate!!.rv.adapter = historyAdapter


        inflate!!.et.setOnEditorActionListener(object : TextView.OnEditorActionListener {
            override fun onEditorAction(v: TextView?, actionId: Int, event: KeyEvent?): Boolean {
                saveHistory(inflate!!.et.text.toString())
                return true
            }

        })
    }

    /**
     * 保存搜索历史
     *
     */
     fun saveHistory(keyWord: String) {
        //查询本地是否有name为参数中的数据
        var histroyBean: HistoryBean? = ObjectBoxUtils.getHistroyBean(keyWord)
        val currentTimeMillis = System.currentTimeMillis()
        //没有就新创建一个
        if (histroyBean == null) {
            histroyBean = HistoryBean(currentTimeMillis, keyWord, currentTimeMillis)
        } else {
            //有的话就更新时间,也就说明了两种情况,第一 重复搜索了,搜索肯定要排重嘛,第二就是我们点击历史记录了,因此更新下时间
            histroyBean.setTime(currentTimeMillis)
        }
        //把新/旧数据保存到本地
        ObjectBoxUtils.addData(histroyBean, HistoryBean::class.java)
        //每一次操作都从数据库拿取数据,性能消耗很低,就这么一个小模块没必要上纲上线
        list?.clear()
        list?.addAll(ObjectBoxUtils.getAllData(HistoryBean::class.java))
        //实体Bean重写了Comparable,排序一下
        list?.sort()
        historyAdapter?.notifyDataSetChanged()
    }
}

相应注释都在代码里,说实话kotlin用的好难受啊,还是自己语法学的不行,一个小东西卡我好久,导致我Application里面直接删除用Java重写了

实体类

@Entity
public class HistoryBean implements Comparable<HistoryBean> {
    @Id(assignable = true)
    public long id;

    public HistoryBean(long id, String name, long time) {
        this.id = id;
        this.name = name;
        this.time = time;
    }

    public String name;

    public long time;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public long getTime() {
        return time;
    }

    public void setTime(long time) {
        this.time = time;
    }


    @Override
    public int compareTo(HistoryBean o) {
        return (int) (o.time-time);
    }
}

实体类重写了CompareTo,因为集合的sort实际上也是调用了ComparteTo,我们直接重写相应逻辑就简化业务层很多代码

效果

历史记录.gif

嗯,效果还不错,继续学习令人脑壳痛的自定义View去了