我正在使用TextWatcher
来过滤listview的结果。但我得到了以下错误:
java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. with Adapter
我没有在任何地方使用后台线程。如何摆脱这个???
@Override
public Filter getFilter() {
// TODO Auto-generated method stub
Filter filter = new Filter() {
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
contactNameList = (ArrayList<String>) results.values;
//Log.e("RESULT:",results.values.toString() );
// getActivity().runOnUiThread(new Runnable() {
// public void run() {
try {
if (results.count > 0) {
mContactListAdapter.notifyDataSetChanged();
} else {
mContactListAdapter.notifyDataSetInvalidated();
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
@Override
protected synchronized FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults(); // Holds the results of a filtering operation in values
ArrayList<String> FilteredArrList = new ArrayList<String>();
// set the Filtered result to return
try {
String sql = "SELECT * FROM "
+MySQLiteHelper.TABLE_NAME_CONTACT
+" WHERE "
+MySQLiteHelper.COLUMN_CNT_NICK_NAME
+" LIKE '"+constraint.toString()+"%'"
+" ORDER BY "
+(prefs.getOrderBy().equalsIgnoreCase("")? MySQLiteHelper.COLUMN_CNT_NICK_NAME: prefs.getOrderBy())
+" COLLATE NOCASE;";
Log.e("FILTER SQL ",sql);
synchronized (this) {
fetchContactData(sql);
}
results.count = contactNameList.size();
results.values = contactNameList;
return results;
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return null;
}
};
return filter;
}
EDIT -Whole logcat:
E/onQueryTextChange(17748): contact onTextChanged:p
08-22 19:18:10.035: E/FILTER SQL(17748): SELECT * FROM contacts WHERE cnt_nick LIKE 'p%' ORDER BY cnt_nick COLLATE NOCASE;
08-22 19:18:10.047: D/AndroidRuntime(17748): Shutting down VM
08-22 19:18:10.048: W/dalvikvm(17748): threadid=1: thread exiting with uncaught exception (group=0x418aa9a8)
08-22 19:18:10.060: E/AndroidRuntime(17748): FATAL EXCEPTION: main
08-22 19:18:10.060: E/AndroidRuntime(17748): java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. [in ListView(2131492994, class android.widget.ListView) with Adapter(class com.ecosmob.contactpro.contacts.ContactFragment$ContactListAdapter)]
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.widget.ListView.layoutChildren(ListView.java:1559)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.widget.AbsListView.onLayout(AbsListView.java:2052)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.View.layout(View.java:14118)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.ViewGroup.layout(ViewGroup.java:4467)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1021)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.View.layout(View.java:14118)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.ViewGroup.layout(ViewGroup.java:4467)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.View.layout(View.java:14118)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.ViewGroup.layout(ViewGroup.java:4467)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.support.v4.view.ViewPager.onLayout(ViewPager.java:1589)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.View.layout(View.java:14118)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.ViewGroup.layout(ViewGroup.java:4467)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1670)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1528)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.widget.LinearLayout.onLayout(LinearLayout.java:1441)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.View.layout(View.java:14118)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.ViewGroup.layout(ViewGroup.java:4467)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.View.layout(View.java:14118)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.ViewGroup.layout(ViewGroup.java:4467)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.support.v4.widget.DrawerLayout.onLayout(DrawerLayout.java:690)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.View.layout(View.java:14118)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.ViewGroup.layout(ViewGroup.java:4467)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.View.layout(View.java:14118)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.ViewGroup.layout(ViewGroup.java:4467)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1670)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1528)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.widget.LinearLayout.onLayout(LinearLayout.java:1441)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.View.layout(View.java:14118)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.ViewGroup.layout(ViewGroup.java:4467)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.View.layout(View.java:14118)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.ViewGroup.layout(ViewGroup.java:4467)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2183)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1947)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1139)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4893)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:776)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.Choreographer.doCallbacks(Choreographer.java:579)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.Choreographer.doFrame(Choreographer.java:548)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:762)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.os.Handler.handleCallback(Handler.java:800)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.os.Handler.dispatchMessage(Handler.java:100)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.os.Looper.loop(Looper.java:194)
08-22 19:18:10.060: E/AndroidRuntime(17748): at android.app.ActivityThread.main(ActivityThread.java:5426)
08-22 19:18:10.060: E/AndroidRuntime(17748): at java.lang.reflect.Method.invokeNative(Native Method)
08-22 19:18:10.060: E/AndroidRuntime(17748): at java.lang.reflect.Method.invoke(Method.java:525)
08-22 19:18:10.060: E/AndroidRuntime(17748): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
08-22 19:18:10.060: E/AndroidRuntime(17748): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
08-22 19:18:10.060: E/AndroidRuntime(17748): at dalvik.system.NativeStart.main(Native Method)
编辑 - 2(SearchBox编辑文字):
searchBox.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,int after) {
// TODO Auto-generated method stub
//Log.e("onQueryTextChange","contact beforeTextChanged:"+ s);
}
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
//Log.e("onQueryTextChange","contact afterTextChanged:"+ s);
try{
searchText = s.toString();
if(searchText.length() > 0){
mContactListAdapter.getFilter().filter(searchText);
}
}catch(Exception e){
e.printStackTrace();
}
Log.e("onQueryTextChange","contact onTextChanged:"+ s);
}
});
答案 0 :(得分:0)
您的代码的某些部分对我没有意义。在performFiltering
方法中,您有以下几行:
results.count = contactNameList.size();
results.values = contactNameList;
然后在publishResults
中,您有以下一行:
contactNameList = (ArrayList<String>) results.values;
我认为您更新contactNameList
的唯一地方是fetchContactData
方法。在后台线程中调用此方法。我相信您在适配器中使用contactNameList
。同样。这就是你得到这个错误的原因。请尝试以下方法:
private ArrayList<String> fetchContactData(String query) {
//Do your query here but DO NOT update contactNameList
return <the arrayList>
}
然后在performFiltering
中替换以下行:
synchronized (this) {
fetchContactData(sql);
}
results.count = contactNameList.size();
results.values = contactNameList;
用这个:
ArrayList<String> temp;
synchronized (this) {
temp = fetchContactData(sql);
}
results.count = temp.size();
results.values = temp;
应该做的伎俩
答案 1 :(得分:0)
我认为问题是在searchBox
中添加快速字符时;它会过快地在数组中获取联系人。意味着notifyDatasetChanged()
没有足够的时间来被召唤。所以,我以下面的解决方案结束了:
searchBox.addTextChangedListener(new TextWatcher() {
private final int TRIGGER_SERACH = 1;
private final long SEARCH_TRIGGER_DELAY_IN_MS = 300;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == TRIGGER_SERACH) {
try{
//if(searchText.length() > 0){
mContactListAdapter.getFilter().filter(searchText);
//}
}catch(Exception e){
e.printStackTrace();
}
}
}
};
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,int after) {
// TODO Auto-generated method stub
//Log.e("onQueryTextChange","contact beforeTextChanged:"+ s);
}
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
//Log.e("onQueryTextChange","contact afterTextChanged:"+ s);
searchText = s.toString();
handler.removeMessages(TRIGGER_SERACH);
handler.sendEmptyMessageDelayed(TRIGGER_SERACH, SEARCH_TRIGGER_DELAY_IN_MS);
Log.e("onQueryTextChange","contact onTextChanged:"+ s);
}
});
这将等待用户输入单词,然后才开始搜索。