Android通訊錄開發之解決快速搜索聯系人線程同步問題
2013年1月13日
上一篇博客介紹的是如何實現搜索,在PhoneUtil中已經定義好瞭search方法,開發者直接拿來用就ok瞭,但用的時候肯定會遇到線程同步問題,如何解決搜索的時候UI線程卡頓的現象,這時候就需要另開一個線程來進行搜索操作瞭,但由於在搜索框輸入字符的時候,一般都是快速輸入的,這就會導致線程同步問題的出現,搜索出來的結果會不對。小巫由於經驗不足還有相關知識的欠缺,在遇到這個問題的時候一直沒能解決,所以隻能去請教有經驗的工程師瞭,最終也找到解決辦法。
在UI線程我們知道超過5秒的操作就會出現卡頓或者ANR對話框,所以一般費時的操作絕不能放在UI線程,但數據的更新和通知就要放在UI線程來實現瞭,比如ListView的adapter的數據更新就要在UI線程裡通知,不然就可能出現數據沒有得到即使更新的現象。
這些問題隻有在實際開發當中才會遇到,我廢話也不多說瞭,下面是解決方案。
搜索框,文本變化的監聽
searchEditText.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(final CharSequence s, int start, int before, int count) { if (!TextUtils.isEmpty(s)) { btnClear.setVisibility(View.VISIBLE); selectAllBtn.setVisibility(View.GONE); searchList(s.toString()); } else {// 如果輸入框內容為空,顯示全部 btnClear.setVisibility(View.GONE); selectAllBtn.setVisibility(View.VISIBLE); searchList(""); } } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(final Editable s) { } });
一般搜索框會有刪除的×,我這裡還有控制顯示全選的框,效果如下:
vc7KzOKjrNa709BpuPpsYXN0ZXN0z+C1yLXEyrG68rLJyKHLotDCwdCx7aOsxuTKtdXiuPaw7LeosqKyu83Bo6yyu9aqtcDN+NPRyse38dPQuPy6w7XEyrXP1re9t6ijrMLpt7PWuL3M0rvPwqGjPC9wPgo8cD48cHJlIGNsYXNzPQ==”brush:java;”> private static int lastest = 0;
// 實現線程同步搜索聯系人
// 線程同步問題可能會導致數據顯示錯誤,比如會顯示上一次搜索到的數據
public void searchList(final String s) {
// 用戶可能正在快速輸入電話號碼,之前在搜索的聯系人列表已經過時瞭。
final int i = ++lastest;
// 開一個線程來進行快速搜索
new Thread(new Runnable() {
@Override
public void run() {
if (TextUtils.isEmpty(s)) {
// 如果輸入的字符串為空,則顯示所有聯系人
searchContacts = allContacts;
} else {
// searhContacts指向搜索返回的list
searchContacts = PhoneUtil.search(s, allContacts);
}
if (i == lastest) { // 避免線程同步問題
LocalContactActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
if (i == lastest) { // 避免線程同步問題
contactList.clear();
contactList.addAll(searchContacts);
refreshList();
}
}
});
}
}
}).start();
}
數據有更新,調用adapter的notifyDataSetChanged()方法就可以達到刷新列表效果。
/** 刷新列表和確認按鈕 **/ public void refreshList() { // adapter.setContactList(contactList); adapter.notifyDataSetChanged(); refreshBtnOK(); }
不知道以上解決方案有沒有幫你解決問題,如果沒有麻煩請告知一聲。
下篇博客會介紹如何實現全選、反選、刪除等功能,敬請期待。