简体   繁体   中英

Writing to SQLite DB from RecycleView Adapter

I have a Main view with one RecyclerView (category_view) in it and another RecyclerView (task_view) in each ViewHolder in category_view. So each Category has several Tasks in it. Data are populated from SQLite DB, I have tables for Categories and Tasks. Also I specified Parcelable for both Category and Task data classes.

Currently I pass a Cursor with Categories table from MainActivity to CategoriesRecyclerAdapter + Database itself. Then in CategoriesRecyclerAdapter I make another Cursor and pass it to TasksRecyclerAdapter.

Actions in nested RecycleView Tasks (checkbox tick) cause changes in both Categories and Tasks SQLite tables.

My question is - how to pass data between these nested adapters without passing whole DB link or DB Open Helper to every ViewHolder?

So currently I'm passing a link to mDb = mDbOpenHelper.getReadableDatabase(), so each Adapter can access it. Now I need to write data to DB, so I can pass either 2 links or 1 link to DBOpenHelper and open DB in each class.viewHolder. I'm not sure that opening a DB in each ViewHolder is a best and optimal solution. Can anyone suggest another solution or confirm that it's ok?

\\Main Activity: make a cursor and pass it to CategoriesRecyclerAdapter
...
private void getCategoriesFromDB() {
    mDb = mDbOpenHelper.getReadableDatabase();
    final Cursor categoryCursor = mDb.query(CategoryEntry.TABLE_NAME, 
    null, null, null, null, null, null);
    mCategoryRecyclerAdapter.changeCursor(categoryCursor, mDb);
}

\\CategoryRecyclerAdapter:
...
public void changeCursor(Cursor cursor, SQLiteDatabase db) {
    if (mCursor != null)
        mCursor.close();
    mCursor = cursor;
    populateColumnPositions();
    notifyDataSetChanged();
    mDb = db;
}

...
public void onBindViewHolder(@NonNull ViewHolder viewHolder, int i) {
    mCursor.moveToPosition(i);

    String selection = TaskEntry.COLUMN_CATEGORY_ID + " = ?";
    String selectionArgs[] = {Integer.toString(mId)};
    final Cursor taskCursor = mDb.query(TaskEntry.TABLE_NAME, null, 
          selection, selectionArgs, null, null, null);

    LinearLayoutManager tasksLayoutManager = new               LinearLayoutManager(viewHolder.mHolderView.getContext());

    TaskRecyclerAdapter taskRecyclerAdapter = new               TaskRecyclerAdapter(viewHolder.mHolderView.getContext(), null, mDb);

    RecyclerView recyclerTasks =                viewHolder.mHolderView.findViewById(R.id.list_tasks);
    recyclerTasks.setLayoutManager(tasksLayoutManager);
    recyclerTasks.setAdapter(taskRecyclerAdapter);

    taskRecyclerAdapter.changeCursor(taskCursor);

}

This is generally a bad idea. You'd ideally want to pass a listener to your adapter, and listen for events in your fragment/activity. From their, you should be using a viewmodel/presenter to communicate with a database layer to make the updates. Based on the result of the operation, success/failure, you can update your adapter with notifyItemChanged, or if adventurous go for a databiniding solution and just update your adapter's data model.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM