在Android中使用选项菜单时无法从SQLite实时加载数据

时间:2018-08-05 11:48:29

标签: sqlite android-recyclerview

嘿,我正在开发一个保持便笺的android应用,我们可以从浮动按钮添加便笺,也可以通过向左或向右滑动来删除便笺。这运作良好。但是,当我想从溢出菜单中删除所有笔记时,它会删除它们,但仍显示所有笔记,当我重新加载应用程序时,它不会显示它们,因此不会动态更新用户界面。在菜单选项中,我还添加了一个用于插入虚拟注释以进行调试的插入虚拟数据选项,但是在我重新加载应用程序之前它不会更新。我添加了摘录的主要活动代码,我将其命名为CatalogActivity,并将自定义适配器类命名为NoteCursorAdapter。请忽略注释的代码部分。

public class CatalogActivity extends AppCompatActivity implements
        LoaderManager.LoaderCallbacks<Cursor>{

    /** Identifier for the pet data loader */
    private static final int NOTE_LOADER_ID = 0;

    /** Adapter for the ListView */
   NoteCursorAdapter mCursorAdapter;

    RecyclerView mRecyclerView;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_catalog);

        // Set the RecyclerView to its corresponding view
        mRecyclerView = findViewById(R.id.list);

        // Set the layout for the RecyclerView to be a linear layout, which measures and
        // positions items within a RecyclerView into a linear list
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));

        // Initialize the adapter and attach it to the RecyclerView
        mCursorAdapter = new NoteCursorAdapter(this);
        mRecyclerView.setAdapter(mCursorAdapter);


         /*
         Add a touch helper to the RecyclerView to recognize when a user swipes to delete an item.
         An ItemTouchHelper enables touch behavior (like swipe and move) on each ViewHolder,
         and uses callbacks to signal when a user is performing these actions.
         */
         new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
             @Override
             public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
                 return false;
             }

             // Called when a user swipes left or right on a ViewHolder
             @Override
             public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {

                 // Here is where you'll implement swipe to delete

                 // COMPLETED (1) 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 = NoteEntry.CONTENT_URI;
                 uri = uri.buildUpon().appendPath(stringId).build();

                 // COMPLETED (2) Delete a single row of data using a ContentResolver
                 getContentResolver().delete(uri, null, null);

                 // COMPLETED (3) Restart the loader to re-query for all tasks after a deletion
                 //getSupportLoaderManager().restartLoader(NOTE_LOADER_ID, null,  CatalogActivity.this);
                 // TODO Check this exception
                 getLoaderManager().restartLoader(NOTE_LOADER_ID, null,  CatalogActivity.this);
             }
         }).attachToRecyclerView(mRecyclerView);

        /*
         Set the Floating Action Button (FAB) to its corresponding View.
         Attach an OnClickListener to it, so that when it's clicked, a new intent will be created
         to launch the AddTaskActivity.
         */
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);

        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(CatalogActivity.this, EditorActivity.class);
                startActivity(intent);
            }
        });

getLoaderManager().initLoader(NOTE_LOADER_ID, null,  this);
    }

    /**
     * This method is called after this activity has been paused or restarted.
     * Often, this is after new data has been inserted through an AddTaskActivity,
     * so this restarts the loader to re-query the underlying data for any changes.
     */
    protected void onResume() {
        super.onResume();

        // Re-queries for all notes
        getLoaderManager().restartLoader(NOTE_LOADER_ID, null,  CatalogActivity.this);
    }



    private void insertNotes() {
        // Create a ContentValues object where column names are the keys,
        // and Particular note attributes are the values
        ContentValues values = new ContentValues();
        values.put(NoteEntry.COLUMN_NOTE_TITLE, "Test");
        values.put(NoteEntry.COLUMN_NOTE_DETAILS, "SQLite");
        values.put(NoteEntry.COLUMN_NOTE_PRIORITY, 0);

        // Insert a new row for a note into the provider using the ContentResolver.
        // Use the {@link NoteEntry#CONTENT_URI} to indicate that we want to insert
        // into the notes database table.
        // Receive the new content URI that will allow us to access Particular data in the future.
        Uri newUri = getContentResolver().insert(NoteEntry.CONTENT_URI, values);
    }

    /*
    * Helper method to delete all notes in the database.
    */
    private void deleteAllNotes() {
        int rowsDeleted = getContentResolver().delete(NoteEntry.CONTENT_URI, null, null);
        Log.v("CatalogActivity", rowsDeleted + " rows deleted from note database");
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu options from the res/menu/menu_catalog.xml file.
        // This adds menu items to the app bar.
        getMenuInflater().inflate(R.menu.menu_catalog, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // User clicked on a menu option in the app bar overflow menu
        switch (item.getItemId()) {
            // Respond to a click on the "Insert dummy data" menu option
            case R.id.action_insert_dummy_data:
                insertNotes();
                return true;
            // Respond to a click on the "Delete all entries" menu option
            case R.id.action_delete_all_entries:
                deleteAllNotes();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }


     * Instantiates and returns a new AsyncTaskLoader with the given ID.
     * This loader will return task data as a Cursor or null if an error occurs.
     *
     * Implements the required callbacks to take care of loading data at all stages of loading.
     */
    @SuppressLint("StaticFieldLeak")
    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
            return new AsyncTaskLoader<Cursor>(this) {

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

            // onStartLoading() is called when a loader first starts loading data

            @Override
            protected void onStartLoading() {
                if (mNoteData != null) {
                    // Delivers any previously loaded data immediately
                    deliverResult(mNoteData);
                } else {
                    // Force 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(NoteContract.NoteEntry.CONTENT_URI,
                            null,
                            null,
                            null,
                            NoteEntry.COLUMN_NOTE_PRIORITY);
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            }

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


    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        // Update {@link NoteCursorAdapter} with this new cursor containing updated pet data
        mCursorAdapter.swapCursor(data);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        // Callback called when the data needs to be deleted
        mCursorAdapter.swapCursor(null);
    }
}



/**
 * {@link NoteCursorAdapter} is an adapter for a list or grid view
 * that uses a {@link Cursor} of pet data as its data source. This adapter knows
 * how to create list items for each row of pet data in the {@link Cursor}.
 */
public class NoteCursorAdapter
        extends RecyclerView.Adapter<NoteCursorAdapter.TaskViewHolder> {

    // Class variables for the Cursor that holds task data and the Context
    private Cursor mCursor;
    private Context mContext;



    public NoteCursorAdapter(Context mContext) {
        this.mContext = mContext;
    }



    @NonNull
    @Override
    public TaskViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        // Inflate the list_item layout to a view
        View view = LayoutInflater.from(mContext).inflate(R.layout.list_item, parent, false);
        return new TaskViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull NoteCursorAdapter.TaskViewHolder holder, int position) {
        // Find the columns of note attributes that we're interested in
        int idColoumnIndex = mCursor.getColumnIndex(NoteContract.NoteEntry._ID);
        int titleColumnIndex = mCursor.getColumnIndex(NoteContract.NoteEntry.COLUMN_NOTE_TITLE);
        int detailColumnIndex = mCursor.getColumnIndex(NoteContract.NoteEntry.COLUMN_NOTE_DETAILS);

        mCursor.moveToPosition(position); // get to the right location in the cursor

        // Determine the values of the wanted data
        final int id = mCursor.getInt(idColoumnIndex);
        String title = mCursor.getString(titleColumnIndex);
        String details = mCursor.getString(detailColumnIndex);

        // Set values
        holder.itemView.setTag(id);
        holder.titleTextView.setText(title);
        holder.detailsTextView.setText(title);

    }

    @Override
    public int getItemCount() {
        if (mCursor == null) {
            return 0;
        }
        return mCursor.getCount();
    }

    /**
     * When data changes and a re-query occurs, this function swaps the old Cursor
     * with a newly updated Cursor (Cursor c) that is passed in.
     */
    public Cursor swapCursor(Cursor c) {
        // check if this cursor is the same as the previous cursor (mCursor)
        if (mCursor == c) {
            return null;
        }
        Cursor temp = mCursor;
        this.mCursor = c;

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

    // Inner class for creating View Holders.
    class TaskViewHolder extends RecyclerView.ViewHolder {

        TextView titleTextView;
        TextView detailsTextView;

        public TaskViewHolder(View itemView) {
            super(itemView);

            titleTextView = itemView.findViewById(R.id.titleNote);
            detailsTextView = itemView.findViewById(R.id.detailsNote);
        }
    }
}

0 个答案:

没有答案