java历史记录_简单的带历史记录的搜索功能实现
这两天闲来⽆事,就把前短时间项⽬中的搜索功能抽取出来,重新写⼀下,搜索功能虽然简单,但是设计到得知识点也挺多的,就当做⼀个总结吧。
代码地址在最后⾯,话不多说,上效果图 _
searchdemo.gif
历史记录的存储
⾸先来说下关于历史记录的存储,历史记录的存储⽅式其实可以有很多⽅法,可以⽤sp,数据库等等,那么就直接开撸吧。说开撸你还真以为就直接开撸了,还是先想想吧,我们做历史记录存储的时候需要提供什么给调⽤者,其实很简单⽆⾮就是可以增删改查吗。为了遵守⾥⽒替换原则,就先写了个抽象类BaseHistoryStorage,⾥⾯有⼏个抽象⽅法,⾄于是什么⾃⼰看吧。这样不管你是⽤SP还是数据库甚⾄其他更⽜的技术,只需要集成Base类,实现这些抽象⽅法就⾏了,⾄于你是怎么实现的,我才不管呢。
/**
* 历史信息存储基类
* Created by Zellerpooh on 17/1/18.
*/
public abstract class BaseHistoryStorage {
/**
* 保存历史记录时调⽤
*
* @param value
*/
public abstract void save(String value);
/**
* 移除单条历史记录
*
* @param key
*/
public abstract void remove(String key);
/**
* 清空历史记录
*/
public abstract void clear();
/**
* ⽣成key
*
*/
public abstract String generateKey();
/**
* 返回排序好的历史记录
*
* @return
*/
public abstract ArrayList sortHistory();
}
上⾯的代码很好理解,SearchHistoryModel是我写的⼀个JavaBean,⾥⾯就放了两个String,⼀个是历史搜索的内容,⼀个是历史记录的Key,其实你直接返回⼀个String泛型的ArrayList的就⾏,但是我这⾥为了⽤SP实现的时候跟快速偷了个懒,好了⾃⼰去实现⼀个历史记录存储功能把。
通过SharedPreference实现数据存储
听到让你⾃⼰去实现是不是⼼凉了⼀半,当然是逗你的了,既然都来了怎么能不给你点福利呢,下⾯我就实现⼀个简单的通过SharedPreference实现的数据存储吧,来抛砖迎⽟吧。
private static SpHistoryStorage instance;
private SpHistoryStorage(Context context, int historyMax) {
this.HISTORY_MAX = historyMax;
}
public static synchronized SpHistoryStorage getInstance(Context context, int historyMax) {
if (instance == null) {
synchronized (SpHistoryStorage.class) {
if (instance == null) {
instance = new SpHistoryStorage(context, historyMax);
}
}
}
return instance;
}
作为⼀个励志成为⾼逼格的⾼级程序员的菜鸟,当然不会放过任何的机会,对于这种⽐较耗资源的数据存储,将他设计为单例模式当然最合适不过了,上⾯就是⼀个简单的DCL的单例模式实现,在安卓中将Context传⼊到单例中是⼀个⼤忌,你试想⼀下你的activity永远得不到释放是⼀件多么恐怖的事情,所以我就换成了applicationContext,反正他是跟随程序⼀直在的。
然后来看看⾥⾯的⽅法实现吧
private static SimpleDateFormat mFormat = new SimpleDateFormat("yyyyMMddHHmmss");
单例模式的几种实现方式
public String generateKey() {
return mFormat.format(new Date());
}
上⾯这个⽅法就是为了存储的时候根据当前时间⽣成的⼀个Key,⽤来判断先后顺序。
@Override
public ArrayList sortHistory() {
Map allHistory = getAll();
ArrayList mResults = new ArrayList<>();
Map hisAll = (Map) getAll();
//将key排序升序
Object[] keys = hisAll.keySet().toArray();
Arrays.sort(keys);
int keyLeng = keys.length;
//这⾥计算 如果历史记录条数是⼤于 可以显⽰的最⼤条数,则⽤最⼤条数做循环条件,防⽌历史记录条数-最⼤条数为负值,数组越界int hisLeng = keyLeng > HISTORY_MAX ? HISTORY_MAX : keyLeng;
for (int i = 1; i <= hisLeng; i++) {
mResults.add(new SearchHistoryModel((String) keys[keyLeng - i], (keys[keyLeng - i])));
}
return mResults;
}
public Map getAll() {
SharedPreferences sp = SharedPreferences(SEARCH_HISTORY,
Context.MODE_PRIVATE);
All();
}
这个⽅法就是从SharedPreferences取出所有的值并且按照时间先后进⾏排序。
@Override
public void save(String value) {
Map historys = (Map) getAll();
for (Map.Entry entry : Set()) {
if (value.Value())) {
Key());
}
}
put(generateKey(), value);
}
保存的⽅法,需要先判断是否已经存在,存在的话就先删除然后根据最新的时间保存。剩下两个移除和清空的⽅法就⾃⼰看吧。
@Override
public void remove(String key) {
SharedPreferences sp = SharedPreferences(SEARCH_HISTORY,
Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editormit();
}
@Override
public void clear() {
SharedPreferences sp = SharedPreferences(SEARCH_HISTORY,
Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.clear();
editormit();
}
好了,通过sharedPreferences存储历史记录的功能就这样完成了,但是⼼⾥⼀想好久没有写数据库相关的代码了,就简单的撸了⼀个通过数据库存储的⽅法,篇幅有限代码就不贴了,想看的点这⾥。其实这⾥的代码借鉴了remusic的搜索记录存储的实现,有什么问题他去→_→。
界⾯的实现
界⾯的实现就⽐较朴素了,毕竟我们都是⽐较注重内在的⼈,代码就不贴了,上⾯⼀个EditText,下⾯⼀个ListView再带上⼀个清空的按钮。界⾯写好了之后呢,先给ListView撸个adapter吧,也很简单继承BaseAdapter,实现下⽅法,然后暴露个接⼝出来,⽤于单条历史记录被点击和删除的时候⽤。
public interface OnSearchHistoryListener {
void onDelete(String key);
void onSelect(String content);
}
holder.layoutClose.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onSearchHistoryListener != null) {
<(position).getTime());
}
}
});
holder.layout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (onSearchHistoryListener != null) {
<(position).getContent());
}
}
});
数据绑定
界⾯撸完了,接着就需要将数据和界⾯联系起来了,这⾥就不得不再推荐⼀下MVP模式了,Model和View都由中间层Presenter来控制,使得逻辑看起来变得很清晰,所以这⾥就⽤MVP模式写了,其实我是怕⾃⼰把各位绕糊涂。
public interface SearchPresenter {
void remove(String key);
void clear();
void sortHistory();
void search(String value);
}
public interface SearchView {
void showHistories(ArrayList results);
void searchSuccess(String value);
}
public interface SearchModel {
void save(String value);
void search(String value,OnSearchListener onSearchListener);
void remove(String key);
void clear();
void sortHistory(OnSearchListener onSearchListener);
}
presenter要做的事情就是,当View被操作后,通知它去做数据操作,即增删改查,⽽Model只需要在p
resenter告诉它做什么的时候去做就⾏,成功之后再回调presenter去通知View,这⾥View就只需要两个操作,搜索成功后界⾯的切换以及历史记录的显⽰。那接下来就来实现⼀下model,presenter和View。