搜索历史记录的实现-Android

语言: CN / TW / HK

highlight: solarized-light theme: simplicity-green


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

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

前言

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

主要逻辑

  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? = 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 { @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去了