Android Activity 从数据库搜索时冻结
Android Activity freezes when search from database
我的 editText 有一个 textWatcher。思路是:
我有两个列表视图,它们在每次插入 editText 字段字符后都会更新。不知何故,我无法使用带过滤方法的标准 ArrayAdapter 来实现这一点。所以我不得不自己实现搜索。一开始它看起来不错,但是当我向我的数据库中添加更多更少的数据时,界面开始冻结。
这是电话
inputSearch.addTextChangedListener(createAndReturnTextWatcher());
这是创建和 returns textWatcher
的方法
private TextWatcher createAndReturnTextWatcher() {
final List<String> list = dbExtractor.getDataForSearchAdapters();
TextWatcher watcher1;
watcher1 = new TextWatcher() {
@Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
if (cs.length() == 0) {
lv.setAdapter(null);
lv2.setAdapter(null);
dc.clickedOnce = true;
dc.decrement();
dc.checkDimCounter();
} else {
setSecondListData(list, String.valueOf(cs));
setFirstListData(list, String.valueOf(cs));
if (dc.clickedOnce) {
dc.increment();
dc.checkDimCounter();
dc.clickedOnce = false;
}
}
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
}
@Override
public void afterTextChanged(Editable arg0) {
}
};
return watcher1;
}
这是执行过滤的方法
private void setSecondListData(List<String> inputData, String cs) {
List<String> result = turkishSearcher.performFiltering(inputData, cs);
ArrayAdapter turkAdapt = new ArrayAdapter(this, R.layout.dictionary_list_item, R.id.product_name,
result);
lv2.setAdapter(turkAdapt);
}
private void setFirstListData(List<String> inputData, String cs) {
List<String> result = normSearcher.performFiltering(inputData, cs);
ArrayAdapter turkAdapt = new ArrayAdapter(this, R.layout.dictionary_list_item, R.id.product_name,
result);
lv.setAdapter(turkAdapt);
}
这是过滤数据的class
public class TurkishSearcher extends Searcher{
@Override
int returnPosition() {
return 1;
}
@Override
String reverse(String couples) {
java.lang.String[] arr = couples.split(" — ");
return arr[1]+ " — " + arr[0];
}
@Override
String replaceTurkish(String words) {
if (checkWithRegExp(words)) {
return words.toLowerCase().replaceAll("ç", "c").replaceAll("ğ", "g").replaceAll("ı", "i").
replaceAll("ö", "o").replaceAll("ş", "s").replaceAll("ü", "u");
} else return words;
}
public static boolean checkWithRegExp(String word){
Pattern p = Pattern.compile("[öçğışü]", Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(word);
return m.find();
}
}
我清楚地知道我保存数据的方式是错误的,而且搜索算法也不是很好。但我的问题是:
是否可以使用线程实现搜索来避免冻结。我可以将两个搜索者放到他们自己的线程中以某种方式避免界面冻结吗?如果可能的话,请告诉我代码中可以使用线程的最佳位置。
提前致谢!
在后台线程中执行长任务的最佳方式。您可以使用 asynctask 来执行此操作。
永远不要因为数据库操作而阻塞主线程。而是使用:
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... unusedParams) {
// TODO: do your database stuff
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
// TODO: refresh UI elements, because thread finished
super.onPostExecute(aVoid);
}
}.execute();
我的 editText 有一个 textWatcher。思路是:
我有两个列表视图,它们在每次插入 editText 字段字符后都会更新。不知何故,我无法使用带过滤方法的标准 ArrayAdapter 来实现这一点。所以我不得不自己实现搜索。一开始它看起来不错,但是当我向我的数据库中添加更多更少的数据时,界面开始冻结。
这是电话
inputSearch.addTextChangedListener(createAndReturnTextWatcher());
这是创建和 returns textWatcher
的方法private TextWatcher createAndReturnTextWatcher() {
final List<String> list = dbExtractor.getDataForSearchAdapters();
TextWatcher watcher1;
watcher1 = new TextWatcher() {
@Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
if (cs.length() == 0) {
lv.setAdapter(null);
lv2.setAdapter(null);
dc.clickedOnce = true;
dc.decrement();
dc.checkDimCounter();
} else {
setSecondListData(list, String.valueOf(cs));
setFirstListData(list, String.valueOf(cs));
if (dc.clickedOnce) {
dc.increment();
dc.checkDimCounter();
dc.clickedOnce = false;
}
}
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
}
@Override
public void afterTextChanged(Editable arg0) {
}
};
return watcher1;
}
这是执行过滤的方法
private void setSecondListData(List<String> inputData, String cs) {
List<String> result = turkishSearcher.performFiltering(inputData, cs);
ArrayAdapter turkAdapt = new ArrayAdapter(this, R.layout.dictionary_list_item, R.id.product_name,
result);
lv2.setAdapter(turkAdapt);
}
private void setFirstListData(List<String> inputData, String cs) {
List<String> result = normSearcher.performFiltering(inputData, cs);
ArrayAdapter turkAdapt = new ArrayAdapter(this, R.layout.dictionary_list_item, R.id.product_name,
result);
lv.setAdapter(turkAdapt);
}
这是过滤数据的class
public class TurkishSearcher extends Searcher{
@Override
int returnPosition() {
return 1;
}
@Override
String reverse(String couples) {
java.lang.String[] arr = couples.split(" — ");
return arr[1]+ " — " + arr[0];
}
@Override
String replaceTurkish(String words) {
if (checkWithRegExp(words)) {
return words.toLowerCase().replaceAll("ç", "c").replaceAll("ğ", "g").replaceAll("ı", "i").
replaceAll("ö", "o").replaceAll("ş", "s").replaceAll("ü", "u");
} else return words;
}
public static boolean checkWithRegExp(String word){
Pattern p = Pattern.compile("[öçğışü]", Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(word);
return m.find();
}
}
我清楚地知道我保存数据的方式是错误的,而且搜索算法也不是很好。但我的问题是:
是否可以使用线程实现搜索来避免冻结。我可以将两个搜索者放到他们自己的线程中以某种方式避免界面冻结吗?如果可能的话,请告诉我代码中可以使用线程的最佳位置。
提前致谢!
在后台线程中执行长任务的最佳方式。您可以使用 asynctask 来执行此操作。
永远不要因为数据库操作而阻塞主线程。而是使用:
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... unusedParams) {
// TODO: do your database stuff
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
// TODO: refresh UI elements, because thread finished
super.onPostExecute(aVoid);
}
}.execute();