我有一个简单的EditText
,TextChangedListener
和ListView
。
onTextChanged
方法将调用以下restartSearch
方法,因此在键入EditText
时应重新启动当前搜索线程。
search
方法只会将匹配项添加到ListView
。
当searchThread
仍处于活动状态时,我想取消并重新启动搜索,以便在输入时UI不会冻结,并且不需要这么长时间。
Thread searchThread;
private void restartSearch(CharSequence cs){
query = cs;
if(searchThread != null && searchThread.isAlive()){
searchThread.interrupt();
}
searchThread = new Thread(new Runnable() {
public void run() {
if(!lastSearch.equals(query))
search(query);
}
});
searchThread.start();
}
我称之为的方法:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText etSearch = ((EditText) findViewById(R.id.etSearch));
//...
etSearch.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
restartSearch(s);
}
//...
});
}
和另一个(我也更新了UI):
final Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.what==1){
//...
adapter.notifyDataSetChanged();
restartSearch(lastSearch);
}
else if(msg.what==2)
adapter.notifyDataSetChanged();
super.handleMessage(msg);
}
};
从msg
方法发送消息search
以更新UI:
private void search(CharSequence s){
searchResults.clear();
if(!s.toString().equals("")){
for(int i=0; i<vocsCount; i++){
try{
getResult(i, 0, 2,s);
getResult(i, 1, 1,s);
}catch(Exception ex){}
}
Collections.sort(searchResults);
}
Message msg = handler.obtainMessage();
msg.what = 2;
handler.sendMessage(msg);
lastSearch = s;
}
因此,每次创建一个新的Runnable
时,似乎它们都是并行的,因为所有搜索项都会多次添加到ListView。
我该如何避免这种情况?
答案 0 :(得分:0)
我认为你真的不需要在这里创建一个线程。因为GUI正在侦听不同的线程,并且它在“onTextChanged”上发出回调,这发生在另一个线程中。如果这些不是两个不同的线程,那么在进行搜索时,您将无法保持GUI响应。
答案 1 :(得分:0)
您正在使用Thread.interrupt()
,但是您是否正在查询线程实现中Thread.interrupted()
的值?
在您完成搜索后从线程中返回结果之前,您应该先检查Thread.interrupted()
- 如果可能的话,您应该更好地进行搜索 -