Search code examples
androidandroid-contentprovider

Injecting a column in content provider


I am using custom built content provider to pull data from my database. There can be many records(like 10k) so instead of implementing some mechanism of lazy loading to a list, I took a chance and created content-provider as it has internally a mechanism for "lazy loading". All works well. I need to add a field (column) which should not go in database, but it is a selector, a check-box. Say this is a list of some users loading from DB, and I want to create something close to WhatsApp "add contacts to broadcast" (see image)

adding contacts

The code for content provider is nothing special:

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    ................
        Cursor cursor = customContactsDataBase.getContacts(id, projection, selection, selectionArgs, sortOrder);
        return cursor;
    }

And getContacts is a simple SQLiteQueryBuilder returning a cursor.

So, my question is, should I inject this new check-box column, if yes, then where to keep the values (in a separate "matching by id" list or a map and dynamically fill the values) Or should I use some other mechanism ?


Solution

  • I've done something similar to this, a shopping list with favourites where you check the favourites to add them to your list.

    I considered it a multi select context action bar (CAB), just forced permanently into the context action bar state. So I applied the same method I use for CABs.

    In my adapter I add an array to hold checked items

    private SparseBooleanArray checkedItems = new SparseBooleanArray();
    

    I have public method in the adapter to toggle a check, get a list of all checked items and a few support methods as below.

    public void toggleChecked(int pos) {
        Log.d(TAG, "Position " + pos);
        if (checkedItems.get(pos, false)) {
            checkedItems.delete(pos);
        } else {
            checkedItems.put(pos, true);
        }
        notifyItemChanged(pos);
    }
    
    public boolean isChecked(int pos) {
        return checkedItems.get(pos, false);
    }
    
    public void clearChecked() {
        checkedItems.clear();
        notifyDataSetChanged();
    }
    
    public int getCheckedItemCount() {
        return checkedItems.size();
    }
    
    public List<Integer> getCheckedItems() {
        List<Integer> items = new ArrayList<>(checkedItems.size());
        for (int i = 0; i < checkedItems.size(); i++) {
            items.add(checkedItems.keyAt(i));
        }
        return items;
    }
    

    You then just need to wire up your viewholder check event to go and update the adapter (I bubble the check event right up to the activity level then back into the adapter as I found it the easiest method with other validation required but that specific to my implementation).