Injecting a list with multiple filters using a cursor adapter

This issue is discussed in this Android question : the wrong item is marked while filtering the list of views . To summarize the problem, when using the list with the CursorAdapter and the filter, the elements selected in the filtered list lose their choice after the filter is deleted, and instead, the elements at this position in the unfiltered list are selected.

Using the sample code in the related question above, where should we put the code to check the boxes. I believe this should be in the getView () method of CustomCursorAdapter, but I'm not sure. In addition, as we access the HashSet, which has all the selected identifiers in the user adapter class, because it will be initialized and changed in the main event containing this list.

My activity implementing ListView

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.selectfriends); Log.v(TAG, "onCreate called") ; selectedIds = new ArrayList<String>() ; selectedLines = new ArrayList<Integer>() ; mDbHelper = new FriendsDbAdapter(this); mDbHelper.open() ; Log.v(TAG, "database opened") ; Cursor c = mDbHelper.fetchAllFriends(); startManagingCursor(c); Log.v(TAG, "fetchAllFriends Over") ; String[] from = new String[] {mDbHelper.KEY_NAME}; int[] to = new int[] { R.id.text1 }; final ListView listView = getListView(); Log.d(TAG, "Got listView"); // Now initialize the adapter and set it to display using our row adapter = new FriendsSimpleCursorAdapter(this, R.layout.selectfriendsrow, c, from, to); Log.d(TAG, "we have got an adapter"); // Initialize the filter-text box //Code adapted from https://stackoverflow.com/questions/1737009/how-to-make-a-nice-looking-listview-filter-on-android filterText = (EditText) findViewById(R.id.filtertext) ; filterText.addTextChangedListener(filterTextWatcher) ; /* Set the FilterQueryProvider, to run queries for choices * that match the specified input. * Code adapted from https://stackoverflow.com/questions/2002607/android-how-to-text-filter-a-listview-based-on-a-simplecursoradapter */ adapter.setFilterQueryProvider(new FilterQueryProvider() { public Cursor runQuery(CharSequence constraint) { // Search for friends whose names begin with the specified letters. Log.v(TAG, "runQuery Constraint = " + constraint) ; String selection = mDbHelper.KEY_NAME + " LIKE '%"+constraint+"%'"; mDbHelper.open(); Cursor c = mDbHelper.fetchFriendsWithSelection( (constraint != null ? constraint.toString() : null)); return c; } }); setListAdapter(adapter); Log.d(TAG, "setListAdapter worked") ; listView.setItemsCanFocus(false); listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); // listView.setOnItemClickListener(mListener); Button btn; btn = (Button)findViewById(R.id.buttondone); mDbHelper.close(); } @Override protected void onListItemClick(ListView parent, View v, int position, long id) { String item = (String) getListAdapter().getItem(position); Toast.makeText(this, item + " selected", Toast.LENGTH_LONG).show(); //gets the Bookmark ID of selected position Cursor cursor = (Cursor)parent.getItemAtPosition(position); String bookmarkID = cursor.getString(0); Log.d(TAG, "mListener -> bookmarkID = " + bookmarkID); Log.d(TAG, "mListener -> position = " + position); // boolean currentlyChecked = checkedStates.get(position); // checkedStates.set(position, !currentlyChecked); if (!selectedIds.contains(bookmarkID)) { selectedIds.add(bookmarkID); selectedLines.add(position); } else { selectedIds.remove(bookmarkID); selectedLines.remove(position); } } private TextWatcher filterTextWatcher = new TextWatcher() { public void afterTextChanged(Editable s) { } public void beforeTextChanged(CharSequence s, int start, int count, int after) { } public void onTextChanged(CharSequence s, int start, int before, int count) { Log.v(TAG, "onTextChanged called. s = " + s); adapter.getFilter().filter(s); } }; @Override protected void onDestroy() { super.onDestroy(); filterText.removeTextChangedListener(filterTextWatcher); } 

My custom cursor adapter:

 public class FriendsSimpleCursorAdapter extends SimpleCursorAdapter implements Filterable { private static final String TAG = "FriendsSimpleCursorAdapter"; private final Context context ; private final String[] values ; private final int layout ; private final Cursor cursor ; static class ViewHolder { public CheckedTextView checkedText ; } public FriendsSimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) { super(context, layout, c, from, to); this.context = context ; this.values = from ; this.layout = layout ; this.cursor = c ; Log.d(TAG, "At the end of the constructor") ; } @Override public View getView(int position, View convertView, ViewGroup parent) { Log.d(TAG, "At the start of rowView. position = " + position) ; View rowView = convertView ; if(rowView == null) { Log.d(TAG, "rowView = null"); try { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); rowView = inflater.inflate(layout, parent, false); Log.d(TAG, "rowView inflated. rowView = " + rowView); ViewHolder viewHolder = new ViewHolder() ; viewHolder.checkedText = (CheckedTextView) rowView.findViewById(R.id.text1) ; rowView.setTag(viewHolder); } catch (Exception e) { Log.e(TAG, "exception = " + e); } } ViewHolder holder = (ViewHolder) rowView.getTag(); int nameCol = cursor.getColumnIndex(FriendsDbAdapter.KEY_NAME) ; String name = cursor.getString(nameCol); holder.checkedText.setText(name); Log.d(TAG, "At the end of rowView"); return rowView; } 

}

+8
android android-listview simplecursoradapter
source share
1 answer

What I did, it solved it:

chickens = cursor. c = internal cursor simplecursoradapter.

in my MainActivity:

 (members) static ArrayList<Boolean> checkedStates = new ArrayList<Boolean>(); static HashSet<String> selectedIds = new HashSet<String>(); static HashSet<Integer> selectedLines = new HashSet<Integer>(); 

in the View onItemClickListener list:

 if (!selectedIds.contains(bookmarkID)) { selectedIds.add(bookmarkID); selectedLines.add(position); } else { selectedIds.remove(bookmarkID); selectedLines.remove(position); if (selectedIds.isEmpty()) { //clear everything selectedIds.clear(); checkedStates.clear(); selectedLines.clear(); //refill checkedStates to avoid force close bug - out of bounds if (cur.moveToFirst()) { while (!cur.isAfterLast()) { MainActivity.checkedStates.add(false); cur.moveToNext(); } } } 

In SimpleCursorAdapter, I added (both in getView):

 // fill the checkedStates array with amount of bookmarks (prevent OutOfBounds Force close) if (c.moveToFirst()) { while (!c.isAfterLast()) { MainActivity.checkedStates.add(false); c.moveToNext(); } } 

and

 String bookmarkID = c.getString(0); CheckedTextView markedItem = (CheckedTextView) row.findViewById(R.id.btitle); if (MainActivity.selectedIds.contains(new String(bookmarkID))) { markedItem.setChecked(true); MainActivity.selectedLines.add(pos); } else { markedItem.setChecked(false); MainActivity.selectedLines.remove(pos); } 

Hope this helps ... you, of course, will need to adapt it to your needs.

EDIT:

FB SDK downloaded, FB registration failed. you have an error when you do not get a valid access_token if the FB application is installed on the device. Removed the FB application and got FC in getFriends() . Having solved it, wrap the area with runOnUiThread(new Runnable...) .

The error you get has nothing to do with poor filtering, the bad state of the flag ... You get it because you are trying to access the cursor before it is requested (already closed). It seems that you close the cursor before the adapter uses it. Check it out by adding:

 mDbHelper = new FriendsDbAdapter(context); mDbHelper.open() ; cursor = mDbHelper.fetchAllFriends(); 

to the getView area in the SelectFriendsAdapter.

After you add this, it will not be FC, and you can start to monitor your filter. Make sure the cursor is not closed, and basically, if you control it with startManagingCursor() , you don't have to manually close it.

Hope you can get it from here!

+1
source share

All Articles