Deleting a single SQlite row RecyclerView onSwiped

本小妞迷上赌 提交于 2019-12-23 04:20:42

问题


I'm storing text items in a RecyclerView adapter and in a Content Provider. The list is accessible from the menu option. Items are deleted by swiping. Currently, the items are being saved, but not deleted. I've debugged and it shows that the "id" is 0(isn't being retrieved in the Main Activity):

int id = (int) viewHolder.itemView.getTag();

The selected item isn't being swiped off the screen. I'm basing my code on this structure:

https://www.javatips.net/api/ud851-Exercises-master/ud851-Exercises-student/Lesson09-ToDo-List/T09.07-Solution-SwipeToDelete/app/src/main/java/com/example/android/todolist/MainActivity.java

I've looked at this thread and the linked threads in that post and my code should work. It worked before in another project. Is the issue with the cursor in the Favorites Adapter class? Thank you in advance.

Swipe to Dismiss for RecyclerView

As well as this thread:

Deleting Row in SQLite in Android

onSwiped and Loader Cursor methods in the Main Activity:

new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT| ItemTouchHelper.RIGHT)
        {
            @Override
            public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target)
            {
                return false;
            }

            @Override
            public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
                if (viewHolder instanceof LinesAdapter.LinesAdapterViewHolder) return 0;
                return super.getSwipeDirs(recyclerView, viewHolder);
            }

            // Called when a user swipes left or right on a ViewHolder
            @Override
            public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
                // Here is where you'll implement swipe to delete

                //Construct the URI for the item to delete
                //[Hint] Use getTag (from the adapter code) to get the id of the swiped item
                // Retrieve the id of the task to delete
                int id = (int) viewHolder.itemView.getTag();

                // Build appropriate uri with String row id appended
                String stringId = Integer.toString(id);
                Uri uri = TubeLineContract.TubeLineEntry.CONTENT_URI;
                uri = uri.buildUpon().appendPath(stringId).build();


               int rowsDeleted = getContentResolver().delete(uri,null, null);
                Log.v("CatalogActivity", rowsDeleted + " rows deleted from the line database");

                getSupportLoaderManager().restartLoader(FAVORITES_LOADER_ID, null, MainActivity.this);
           }
       }).attachToRecyclerView(mLineRecyclerView);

        /*
         *  Starting the asyncTask so that lines load upon launching the app.
         */
        if (savedInstanceState == null)
        {
            if (isNetworkStatusAvailable(this))
            {
                TubeLineAsyncTask myLineTask = new TubeLineAsyncTask(this);
                myLineTask.execute(NetworkUtils.buildLineUrl());

            } else
                {
                Snackbar
                        .make(mCoordinatorLayout, "Please check your internet connection", Snackbar.LENGTH_INDEFINITE)
                        .setAction("Retry", new MyClickListener())
                        .show();
            }
        } else {

            linesArrayList = savedInstanceState.getParcelableArrayList(KEY_LINES_LIST);
            linesAdapter.setLinesList(linesArrayList);
        }
     getSupportLoaderManager().initLoader(FAVORITES_LOADER_ID, null, MainActivity.this);
        favoritesAdapter = new FavoritesAdapter(this, MainActivity.this);
  }



@Override
    public Loader<Cursor> onCreateLoader(int id, final Bundle loaderArgs)
    {
        return new AsyncTaskLoader<Cursor>(this)
        {

            // Initialize a Cursor, this will hold all the task data
            Cursor mFavoritesData = null;

            // onStartLoading() is called when a loader first starts loading data
            @Override
            protected void onStartLoading()
            {
                if (mFavoritesData != null)
                {
                    // Delivers any previously loaded data immediately
                    deliverResult(mFavoritesData);
                }
                else
                {
                    // Force a new load
                    forceLoad();
                }
            }

            // loadInBackground() performs asynchronous loading of data
            @Override
            public Cursor loadInBackground()
            {
                // Will implement to load data

                // Query and load all task data in the background; sort by priority
                // [Hint] use a try/catch block to catch any errors in loading data
                try
                {
                    return getContentResolver().query(TubeLineContract.TubeLineEntry.CONTENT_URI,
                            null,
                            null,
                            null,
                             TubeLineContract.TubeLineEntry.COLUMN_LINES_ID);
                }
                catch (Exception e)
                {
                    Log.e(LOG_TAG, "Failed to asynchronously load data.");
                    e.printStackTrace();
                    return null;
                }
            }

            // deliverResult sends the result of the load, a Cursor, to the registered listener
            public void deliverResult(Cursor data)
            {
                mFavoritesData = data;
                super.deliverResult(data);
            }
        };
    }

    /**
     * Called when a previously created loader has finished its load.
     *
     * @param loader The Loader that has finished.
     * @param data   The data generated by the Loader.
     */
    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data)
    {
        favoritesAdapter.swapCursor(data);
        if (mPosition == RecyclerView.NO_POSITION) mPosition = 0;
        mLineRecyclerView.smoothScrollToPosition(mPosition);
    }

    /**
     * Called when a previously created loader is being reset, and thus
     * making its data unavailable.
     * onLoaderReset removes any references this activity had to the loader's data.
     *
     * @param loader The Loader that is being reset.
     */
    @Override
    public void onLoaderReset(Loader<Cursor> loader)
    {
        favoritesAdapter.swapCursor(null);
    }

ContentProvider delete method:

// Implement delete to delete a single row of data
    @Override
    public int delete(@NonNull Uri uri, String selection, String[] selectionArgs)
    {
        // Get access to the database and write URI matching code to recognize a single item
        final SQLiteDatabase db = mTubeLineDbHelper.getWritableDatabase();

        int match = sUriMatcher.match(uri);
        // Keep track of the number of deleted rows
        int rowsDeleted; // starts as 0

        //if (null == selection) selection = "1";
        // Write the code to delete a single row of data
        // [Hint] Use selections to delete an item by its row ID
        switch (match)
        {
            // Handle the single item case, recognized by the ID included in the URI path
            case LINE_WITH_ID:
                // Get the line ID from the URI path
               String id = uri.getPathSegments().get(1);
                // Use selections/selectionArgs to filter for this ID

            rowsDeleted = db.delete(TubeLineContract.TubeLineEntry.TABLE_NAME, "id=?", new String[]{id});

                break;
            default:
                throw new UnsupportedOperationException("Unknown uri: " + uri);
        }

        // Notify the resolver of a change and return the number of items deleted
        if (rowsDeleted != 0)
        {
            // A line was deleted, set notification
            getContext().getContentResolver().notifyChange(uri, null);
        }

        // Return the number of rows deleted
        return rowsDeleted;
    }

RecyclerViewAdapter:

public class FavoritesAdapter extends RecyclerView.Adapter<FavoritesAdapter.FavoritesAdapterViewHolder>
{
    private static final String TAG = FavoritesAdapter.class.getSimpleName();

    private Context context;
    private Cursor cursor;
    private LinesAdapter.LinesAdapterOnClickHandler mClickHandler;

    public FavoritesAdapter(LinesAdapter.LinesAdapterOnClickHandler clickHandler, Context context)
    {
        mClickHandler = clickHandler;
        this.context = context;
    }
    public class FavoritesAdapterViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        @BindView(R.id.line_name)
        TextView lineName;

        public FavoritesAdapterViewHolder(View view) {
            super(view);
            ButterKnife.bind(this, view);
            view.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            cursor.moveToPosition(getAdapterPosition());

            String lineName = cursor.getString(cursor.getColumnIndexOrThrow(TubeLineContract.TubeLineEntry.COLUMN_LINES_NAME));
            String lineId = cursor.getString(cursor.getColumnIndexOrThrow(TubeLineContract.TubeLineEntry.COLUMN_LINES_ID));

            Lines lines = new Lines(lineName, lineId);

            mClickHandler.onClick(lines);
        }
    }

    @Override
        public void onBindViewHolder(FavoritesAdapter.FavoritesAdapterViewHolder holder, int position)
        {
            // get to the right location in the cursor
            cursor.moveToPosition(position);

            // Determine the values of the wanted data
            int lineIdIndex = cursor.getColumnIndexOrThrow(TubeLineContract.TubeLineEntry.COLUMN_LINES_ID);
            int lineNameColumnIndex = cursor.getColumnIndexOrThrow(TubeLineContract.TubeLineEntry.COLUMN_LINES_NAME);

            final int id = cursor.getInt(lineIdIndex);
            String stationName = cursor.getString(lineNameColumnIndex);

            holder.itemView.setTag(id);
            holder.lineName.setText(stationName);
            Log.e(TAG, "Failed to load line text.");

        }

        @Override
        public FavoritesAdapter.FavoritesAdapterViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType)
        {
            Context context = viewGroup.getContext();
            int layoutIdForListItem = R.layout.line_list_item;
            LayoutInflater inflater = LayoutInflater.from(context);
            boolean shouldAttachToParentImmediately = false;
            View view = inflater.inflate(layoutIdForListItem, viewGroup, shouldAttachToParentImmediately);
            return new FavoritesAdapter.FavoritesAdapterViewHolder(view);
        }

        public Cursor swapCursor(Cursor c)
        {
            // check if this cursor is the same as the previous cursor (mCursor)
            if (cursor == c)
            {
                return null; // bc nothing has changed
            }

            Cursor temp = cursor;
            this.cursor = c; // new cursor value assigned

            //check if this is a valid cursor, then update the cursor
            if (c != null)
            {
                this.notifyDataSetChanged();
            }
            return temp;
        }

        @Override
        public int getItemCount()
        {
            if (null == cursor)
                return 0;

            return cursor.getCount();

        }
    }

回答1:


Change

rowsDeleted = db.delete(TubeLineContract.TubeLineEntry.TABLE_NAME, "id=?", new String[]{id});

To

rowsDeleted = db.delete(TubeLineContract.TubeLineEntry.TABLE_NAME, "id=?", new String[]{String.valueOf(id)});

in ContentProvider delete method.



来源:https://stackoverflow.com/questions/54300848/deleting-a-single-sqlite-row-recyclerview-onswiped

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!