summaryrefslogtreecommitdiff
path: root/samples/NotePad/src/com/example/android/notepad/NoteEditor.java
diff options
context:
space:
mode:
authorJoe Malin <jmalin@google.com>2010-06-07 16:26:25 -0700
committerJoe Malin <jmalin@google.com>2010-08-09 15:30:01 -0700
commit4124e0a1f07e4e54c37b0cfbb1b7438806ff02a6 (patch)
tree044d57a235802491100ea89ace9c8f56c9471e30 /samples/NotePad/src/com/example/android/notepad/NoteEditor.java
parent4779ab6f9aa4d6b691f051e069ffac31475f850a (diff)
Revised Note Pad sample, new test app for Note Pad
Change-Id: Ia41a33d935ead704c1de439a0cfb0a55806cfe12
Diffstat (limited to 'samples/NotePad/src/com/example/android/notepad/NoteEditor.java')
-rw-r--r--samples/NotePad/src/com/example/android/notepad/NoteEditor.java555
1 files changed, 376 insertions, 179 deletions
diff --git a/samples/NotePad/src/com/example/android/notepad/NoteEditor.java b/samples/NotePad/src/com/example/android/notepad/NoteEditor.java
index 57b464678..d01974e7a 100644
--- a/samples/NotePad/src/com/example/android/notepad/NoteEditor.java
+++ b/samples/NotePad/src/com/example/android/notepad/NoteEditor.java
@@ -16,13 +16,10 @@
package com.example.android.notepad;
-import com.example.android.notepad.NotePad.Notes;
+import com.example.android.notepad.NotePad;
import android.app.Activity;
-import android.content.ClipboardManager;
-import android.content.ClippedData;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
@@ -39,28 +36,31 @@ import android.view.MenuItem;
import android.widget.EditText;
/**
- * A generic activity for editing a note in a database. This can be used
- * either to simply view a note {@link Intent#ACTION_VIEW}, view and edit a note
- * {@link Intent#ACTION_EDIT}, or create a new empty note
- * {@link Intent#ACTION_INSERT}, or create a new note from the current contents
- * of the clipboard {@link Intent#ACTION_PASTE}.
+ * This Activity handles "editing" a note, where editing is responding to
+ * {@link Intent#ACTION_VIEW} (request to view data), edit a note
+ * {@link Intent#ACTION_EDIT}, or create a note {@link Intent#ACTION_INSERT}.
+ *
+ * NOTE: Notice that the provider operations in this Activity are taking place on the UI thread.
+ * This is not a good practice. It is only done here to make the code more readable. A real
+ * application should use the {@link android.content.AsyncQueryHandler}
+ * or {@link android.os.AsyncTask} object to perform operations asynchronously on a separate thread.
*/
public class NoteEditor extends Activity {
+ // For logging and debugging purposes
private static final String TAG = "Notes";
- /**
- * Standard projection for the interesting columns of a normal note.
+ /*
+ * Creates a projection that returns the note ID and the note contents.
*/
- private static final String[] PROJECTION = new String[] {
- Notes._ID, // 0
- Notes.NOTE, // 1
- Notes.TITLE, // 2
+ private static final String[] PROJECTION
+ = new String[] {
+ NotePad.Notes._ID,
+ NotePad.Notes.COLUMN_NAME_NOTE
};
+
/** The index of the note column */
private static final int COLUMN_INDEX_NOTE = 1;
- /** The index of the title column */
- private static final int COLUMN_INDEX_TITLE = 2;
-
+
// This is our state data that is stored when freezing.
private static final String ORIGINAL_CONTENT = "origContent";
@@ -72,73 +72,111 @@ public class NoteEditor extends Activity {
// The different distinct states the activity can be run in.
private static final int STATE_EDIT = 0;
private static final int STATE_INSERT = 1;
- private static final int STATE_PASTE = 2;
+ // Global variables
private int mState;
- private boolean mNoteOnly = false;
private Uri mUri;
private Cursor mCursor;
private EditText mText;
private String mOriginalContent;
/**
- * A custom EditText that draws lines between each line of text that is displayed.
+ * Defines a custom EditText View that draws lines between each line of text that is displayed.
*/
public static class LinedEditText extends EditText {
private Rect mRect;
private Paint mPaint;
- // we need this constructor for LayoutInflater
+ // This constructor is used by LayoutInflater
public LinedEditText(Context context, AttributeSet attrs) {
super(context, attrs);
-
+
+ // Creates a Rect and a Paint object, and sets the style and color of the Paint object.
mRect = new Rect();
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(0x800000FF);
}
-
+
+ /**
+ * This is called to draw the LinedEditText object
+ * @param canvas The canvas on which the background is drawn.
+ */
@Override
protected void onDraw(Canvas canvas) {
+
+ // Gets the number of lines of text in the View.
int count = getLineCount();
+
+ // Gets the global Rect and Paint objects
Rect r = mRect;
Paint paint = mPaint;
+ /*
+ * Draws one line in the rectangle for every line of text in the EditText
+ */
for (int i = 0; i < count; i++) {
+
+ // Gets the baseline coordinates for the current line of text
int baseline = getLineBounds(i, r);
+ // Draws a line in the background from the left of the rectangle to the right,
+ // at a vertical position one dip below the baseline, using the "paint" object
+ // for details.
canvas.drawLine(r.left, baseline + 1, r.right, baseline + 1, paint);
}
+ // Finishes up by calling the parent method
super.onDraw(canvas);
}
}
+ /**
+ * This method is called by Android when the Activity is first started. From the incoming
+ * Intent, it determines what kind of editing is desired, and then does it.
+ */
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ /*
+ * Creates an Intent to use when the Activity object's result is sent back to the
+ * caller.
+ */
final Intent intent = getIntent();
- // Do some setup based on the action being performed.
+ /*
+ * Sets up for the edit, based on the action specified for the incoming Intent.
+ */
+ // Gets the action that triggered the intent filter for this Activity
final String action = intent.getAction();
+
+ // For an edit action:
if (Intent.ACTION_EDIT.equals(action)) {
- // Requested to edit: set that state, and the data being edited.
+
+ // Sets the Activity state to EDIT, and gets the URI for the data to be edited.
mState = STATE_EDIT;
mUri = intent.getData();
- } else if (Intent.ACTION_INSERT.equals(action)
- || Intent.ACTION_PASTE.equals(action)) {
- // Requested to insert: set that state, and create a new entry
- // in the container.
+
+ // For an insert action:
+ } else if (Intent.ACTION_INSERT.equals(action)) {
+
+ // Sets the Activity state to INSERT, gets the general note URI, and inserts an
+ // empty record in the provider
mState = STATE_INSERT;
mUri = getContentResolver().insert(intent.getData(), null);
- // If we were unable to create a new note, then just finish
- // this activity. A RESULT_CANCELED will be sent back to the
- // original activity if they requested a result.
+ /*
+ * If the attempt to insert the new note fails, shuts down this Activity. The
+ * originating Activity receives back RESULT_CANCELED if it requested a result.
+ * Logs that the insert failed.
+ */
if (mUri == null) {
+ // Writes the log identifier, a message, and the URI that failed.
Log.e(TAG, "Failed to insert new note into " + getIntent().getData());
+
+ // Closes the activity.
finish();
return;
}
@@ -147,266 +185,425 @@ public class NoteEditor extends Activity {
// set the result to be returned.
setResult(RESULT_OK, (new Intent()).setAction(mUri.toString()));
- // If pasting, initialize data from clipboard.
- if (Intent.ACTION_PASTE.equals(action)) {
- performPaste();
- // Switch to paste mode; can no longer modify title.
- mState = STATE_PASTE;
- }
-
+ // If the action was other than EDIT or INSERT:
} else {
- // Whoops, unknown action! Bail.
+ // Logs an error that the action was not understood, finishes the Activity, and
+ // returns RESULT_CANCELED to an originating Activity.
Log.e(TAG, "Unknown action, exiting");
finish();
return;
}
- // Set the layout for this activity. You can find it in res/layout/note_editor.xml
+ // Sets the layout for this Activity. See res/layout/note_editor.xml
setContentView(R.layout.note_editor);
-
- // The text view for our note, identified by its ID in the XML file.
- mText = (EditText) findViewById(R.id.note);
- // Get the note!
- mCursor = managedQuery(mUri, PROJECTION, null, null, null);
+ // Gets a handle to the EditText in the the layout.
+ mText = (EditText) findViewById(R.id.note);
- // If an instance of this activity had previously stopped, we can
- // get the original text it started with.
+ /*
+ * Using the URI passed in with the triggering Intent, gets the note or notes in
+ * the provider.
+ * Note: This is being done on the UI thread. It will block the thread until the query
+ * completes. In a sample app, going against a simple provider based on a local database,
+ * the block will be momentary, but in a real app you should use
+ * android.content.AsyncQueryHandler or android.os.AsyncTask.
+ */
+ mCursor = managedQuery(
+ mUri, // The URI that gets multiple notes from the provider.
+ PROJECTION, // A projection that returns the note ID and note content for each note.
+ null, // No "where" clause selection criteria.
+ null, // No "where" clause selection values.
+ null // Use the default sort order (modification date, descending)
+ );
+
+ /*
+ * If this Activity had stopped previously, its state was written the ORIGINAL_CONTENT
+ * location in the saved Instance state. This gets the state.
+ */
if (savedInstanceState != null) {
mOriginalContent = savedInstanceState.getString(ORIGINAL_CONTENT);
}
}
+ /**
+ * This method is called when the Activity is about to come to the foreground. This happens
+ * when the Activity comes to the top of the task stack, OR when it is first starting.
+ *
+ * Moves to the first note in the list, sets an appropriate title for the action chosen by
+ * the user, puts the note contents into the TextView, and saves the original text as a
+ * backup.
+ */
@Override
protected void onResume() {
super.onResume();
- // If we didn't have any trouble retrieving the data, it is now
- // time to get at the stuff.
+ /*
+ * mCursor is initialized, since onCreate() always precedes onResume for any running
+ * process. This tests that it's not null, since it should always contain data.
+ */
if (mCursor != null) {
- // Make sure we are at the one and only row in the cursor.
+
+ /* Moves to the first record. Always call moveToFirst() before accessing data in
+ * a Cursor for the first time. The semantics of using a Cursor are that when it is
+ * created, its internal index is pointing to a "place" immediately before the first
+ * record.
+ */
mCursor.moveToFirst();
- // Modify our overall title depending on the mode we are running in.
+ // Modifies the window title for the Activity according to the current Activity state.
if (mState == STATE_EDIT) {
+
+ // Sets the title to "edit"
setTitle(getText(R.string.title_edit));
- } else if (mState == STATE_INSERT || mState == STATE_PASTE) {
+ } else if (mState == STATE_INSERT) {
+
+ // Sets the title to "create"
setTitle(getText(R.string.title_create));
}
- // This is a little tricky: we may be resumed after previously being
- // paused/stopped. We want to put the new text in the text view,
- // but leave the user where they were (retain the cursor position
- // etc). This version of setText does that for us.
+ /*
+ * onResume() may have been called after the Activity lost focus (was paused).
+ * The user was either editing or creating a note when the Activity paused.
+ * The Activity should re-display the text that had been retrieved previously, but
+ * it should not move the cursor. This helps the user to continue editing or entering.
+ */
+
+ // Gets the note text from the Cursor and puts it in the TextView, but doesn't change
+ // the text cursor's position.
String note = mCursor.getString(COLUMN_INDEX_NOTE);
mText.setTextKeepState(note);
-
- // If we hadn't previously retrieved the original text, do so
- // now. This allows the user to revert their changes.
+
+ // Stores the original note text, to allow the user to revert changes.
if (mOriginalContent == null) {
mOriginalContent = note;
}
+ /*
+ * Something is wrong. The Cursor should always contain data. Report an error in the
+ * note.
+ */
} else {
setTitle(getText(R.string.error_title));
mText.setText(getText(R.string.error_message));
}
}
+ /**
+ * This method is called when an Activity loses focus during its normal operation, and is then
+ * later on killed. The Activity has a chance to save its state so that the system can restore
+ * it.
+ *
+ * Notice that this method isn't a normal part of the Activity lifecycle. It won't be called
+ * if the user simply navigates away from the Activity.
+ */
@Override
protected void onSaveInstanceState(Bundle outState) {
- // Save away the original text, so we still have it if the activity
+ // Saves away the original text, so we still have it if the activity
// needs to be killed while paused.
outState.putString(ORIGINAL_CONTENT, mOriginalContent);
}
+ /**
+ * This method is called when the Activity loses focus.
+ *
+ * For Activity objects that edit information, onPause() may be the one place where changes are
+ * saved. The Android application model is predicated on the idea that "save" and "exit" aren't
+ * required actions. When users navigate away from an Activity, they shouldn't have to go back
+ * to it to complete their work. The act of going away should save everything and leave the
+ * Activity in a state where Android can destroy it if necessary.
+ *
+ * If the user hasn't done anything, then this deletes or clears out the note, otherwise it
+ * writes the user's work to the provider.
+ */
@Override
protected void onPause() {
super.onPause();
- // The user is going somewhere else, so make sure their current
- // changes are safely saved away in the provider. We don't need
- // to do this if only editing.
+ /*
+ * Tests to see that the query operation didn't fail (see onCreate()). The Cursor object
+ * will exist, even if no records were returned, unless the query failed because of some
+ * exception or error.
+ *
+ */
if (mCursor != null) {
- String text = mText.getText().toString();
- int length = text.length();
- // If this activity is finished, and there is no text, then we
- // do something a little special: simply delete the note entry.
- // Note that we do this both for editing and inserting... it
- // would be reasonable to only do it when inserting.
- if (isFinishing() && (length == 0) && !mNoteOnly) {
+ // Get the current note text.
+ String text = mText.getText().toString();
+ int note_length = text.length();
+
+ /*
+ * If the Activity is in the midst of finishing and there is no text in the current
+ * note, returns a result of CANCELED to the caller, and deletes the note. This is done
+ * even if the note was being edited, the assumption being that the user wanted to
+ * "clear out" (delete) the note.
+ */
+ if (isFinishing() && (note_length == 0)) {
setResult(RESULT_CANCELED);
deleteNote();
- // Get out updates into the provider.
+ /*
+ * Writes the edits to the provider. The note has been edited if an existing note was
+ * retrieved into the editor *or* if a new note was inserted. In the latter case,
+ * onCreate() inserted a new empty note into the provider, and it is this new note
+ * that is being edited.
+ */
} else {
- updateNote(text, null, !mNoteOnly);
+ // Creates a map to contain the new values for the columns
+ ContentValues values = new ContentValues();
+
+ // In the values map, sets the modification date column to the current time.
+ values.put(NotePad.Notes.COLUMN_NAME_MODIFICATION_DATE, System.currentTimeMillis());
+
+ // Creates a title for a newly-inserted note.
+ if (mState == STATE_INSERT) {
+
+ // Gets the first 30 characters of the note, or the entire note if it's
+ // less than 30 characters long.
+ String title = text.substring(0, Math.min(30, note_length));
+
+ // If the note's entire length is greater than 30, then the title is 30
+ // characters long. Finds the last occurrence of blank in the title, and
+ // removes all characters to the right of it from the title string.
+ if (note_length > 30) {
+ int lastSpace = title.lastIndexOf(' ');
+ if (lastSpace > 0) {
+ title = title.substring(0, lastSpace);
+ }
+ }
+ // In the values map, set the title column to the new title.
+ values.put(NotePad.Notes.COLUMN_NAME_TITLE, title);
+ }
+
+ // In the values map, sets the note text column to the text in the View.
+ values.put(NotePad.Notes.COLUMN_NAME_NOTE, text);
+
+ /*
+ * Updates the provider with the new values in the map. The ListView is updated
+ * automatically. The provider sets this up by setting the notification URI for
+ * query Cursor objects to the incoming URI. The content resolver is thus
+ * automatically notified when the Cursor for the URI changes, and the UI is
+ * updated.
+ * Note: This is being done on the UI thread. It will block the thread until the
+ * update completes. In a sample app, going against a simple provider based on a
+ * local database, the block will be momentary, but in a real app you should use
+ * android.content.AsyncQueryHandler or android.os.AsyncTask.
+ */
+ getContentResolver().update(
+ mUri, // The URI for the record to update.
+ values, // The map of column names and new values to apply to them.
+ null, // No selection criteria are used, so no where columns are necessary.
+ null // No where columns are used, so no where arguments are necessary.
+ );
}
}
}
+ /**
+ * This method is called when the user clicks the device's Menu button the first time for
+ * this Activity. Android passes in a Menu object that is populated with items.
+ *
+ * Builds the menus for editing and inserting, and adds in alternative actions that
+ * registered themselves to handle the MIME types for this application.
+ *
+ * @param menu A Menu object to which items should be added.
+ * @return True to display the menu.
+ */
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
- // Build the menus that are shown when editing.
+ // Builds the menus that are shown when editing. These are 'revert' to undo changes, and
+ // 'delete' to delete the note.
if (mState == STATE_EDIT) {
+
+ // Adds the 'revert' menu item, and sets its shortcut to numeric 0, letter 'r' and its
+ // icon to the Android standard revert icon.
menu.add(0, REVERT_ID, 0, R.string.menu_revert)
- .setShortcut('0', 'r')
- .setIcon(android.R.drawable.ic_menu_revert);
- if (!mNoteOnly) {
- menu.add(0, DELETE_ID, 0, R.string.menu_delete)
- .setShortcut('1', 'd')
- .setIcon(android.R.drawable.ic_menu_delete);
- }
+ .setShortcut('0', 'r')
+ .setIcon(android.R.drawable.ic_menu_revert);
+
+ // Adds the 'delete' menu item, and sets its shortcut to numeric 1, letter 'd' and its
+ // icon to the Android standard delete icon
+ menu.add(0, DELETE_ID, 0, R.string.menu_delete)
+ .setShortcut('1', 'd')
+ .setIcon(android.R.drawable.ic_menu_delete);
- // Build the menus that are shown when inserting.
+ // Builds the menus that are shown when inserting. The only option is 'Discard' to throw
+ // away the new note.
} else {
+
+ // Adds the 'discard' menu item, using the 'delete' shortcuts and icon.
menu.add(0, DISCARD_ID, 0, R.string.menu_discard)
.setShortcut('0', 'd')
.setIcon(android.R.drawable.ic_menu_delete);
}
- // If we are working on a full note, then append to the
- // menu items for any other activities that can do stuff with it
- // as well. This does a query on the system for any activities that
- // implement the ALTERNATIVE_ACTION for our data, adding a menu item
- // for each one that is found.
- if (!mNoteOnly) {
- Intent intent = new Intent(null, getIntent().getData());
- intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
- menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0,
- new ComponentName(this, NoteEditor.class), null, intent, 0, null);
- }
-
+ /*
+ * Appends menu items for any Activity declarations that implement an alternative action
+ * for this Activity's MIME type, one menu item for each Activity.
+ */
+ // Makes a new Intent with the URI data passed to this Activity
+ Intent intent = new Intent(null, getIntent().getData());
+
+ // Adds the ALTERNATIVE category to the Intent.
+ intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
+
+ /*
+ * Constructs a new ComponentName object that represents the current Activity.
+ */
+ ComponentName component = new ComponentName(
+ this,
+ NoteEditor.class);
+
+ /*
+ * In the ALTERNATIVE menu group, adds an option for each Activity that is registered to
+ * handle this Activity's MIME type. The Intent describes what type of items should be
+ * added to the menu; in this case, Activity declarations with category ALTERNATIVE.
+ */
+ menu.addIntentOptions(
+ Menu.CATEGORY_ALTERNATIVE, // The menu group to add the items to.
+ Menu.NONE, // No unique ID is needed.
+ Menu.NONE, // No ordering is needed.
+ component, // The current Activity object's component name
+ null, // No specific items need to be placed first.
+ intent, // The intent containing the type of items to add.
+ Menu.NONE, // No flags are necessary.
+ null // No need to generate an array of menu items.
+ );
+
+ // The method returns TRUE, so that further menu processing is not done.
return true;
}
+ /**
+ * This method is called when a menu item is selected. Android passes in the selected item.
+ * The switch statement in this method calls the appropriate method to perform the action the
+ * user chose.
+ *
+ * @param item The selected MenuItem
+ * @return True to indicate that the item was processed, and no further work is necessary. False
+ * to proceed to further processing as indicated in the MenuItem object.
+ */
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- // Handle all of the possible menu actions.
+ // Chooses the action to perform
switch (item.getItemId()) {
+
+ // Deletes the note and close the Activity.
case DELETE_ID:
deleteNote();
finish();
break;
+
+ // Discards the new note.
case DISCARD_ID:
cancelNote();
break;
+
+ // Discards any changes to an edited note.
case REVERT_ID:
cancelNote();
break;
}
- return super.onOptionsItemSelected(item);
- }
-
-//BEGIN_INCLUDE(paste)
- /**
- * Replace the note's data with the current contents of the clipboard.
- */
- private final void performPaste() {
- ClipboardManager clipboard = (ClipboardManager)
- getSystemService(Context.CLIPBOARD_SERVICE);
- ContentResolver cr = getContentResolver();
-
- ClippedData clip = clipboard.getPrimaryClip();
- if (clip != null) {
- String text=null, title=null;
-
- ClippedData.Item item = clip.getItem(0);
- Uri uri = item.getUri();
- if (uri != null && NotePad.Notes.CONTENT_ITEM_TYPE.equals(cr.getType(uri))) {
- // The clipboard holds a reference to a note. Copy it.
- Cursor orig = cr.query(uri, PROJECTION, null, null, null);
- if (orig != null) {
- if (orig.moveToFirst()) {
- text = orig.getString(COLUMN_INDEX_NOTE);
- title = orig.getString(COLUMN_INDEX_TITLE);
- }
- orig.close();
- }
- }
-
- // If we weren't able to load the clipped data as a note, then
- // convert whatever it is to text.
- if (text == null) {
- text = item.coerceToText(this).toString();
- }
-
- updateNote(text, title, true);
- }
- }
-//END_INCLUDE(paste)
-
- /**
- * Replace the current note contents with the given data.
- */
- private final void updateNote(String text, String title, boolean updateTitle) {
- ContentValues values = new ContentValues();
-
- // This stuff is only done when working with a full-fledged note.
- if (updateTitle) {
- // Bump the modification time to now.
- values.put(Notes.MODIFIED_DATE, System.currentTimeMillis());
-
- // If we are creating a new note, then we want to also create
- // an initial title for it.
- if (mState == STATE_INSERT) {
- if (title == null) {
- int length = text.length();
- title = text.substring(0, Math.min(30, length));
- if (length > 30) {
- int lastSpace = title.lastIndexOf(' ');
- if (lastSpace > 0) {
- title = title.substring(0, lastSpace);
- }
- }
- }
- values.put(Notes.TITLE, title);
- }
- }
-
- // Write our text back into the provider.
- values.put(Notes.NOTE, text);
-
- // Commit all of our changes to persistent storage. When the update completes
- // the content provider will notify the cursor of the change, which will
- // cause the UI to be updated.
- getContentResolver().update(mUri, values, null, null);
+ // Continues with processing the menu item. In effect, if the item was an alternative
+ // action, this invokes the Activity for that action.
+ return super.onOptionsItemSelected(item);
}
/**
- * Take care of canceling work on a note. Deletes the note if we
+ * Takes care of canceling work on a note. Deletes the note if we
* had created it, otherwise reverts to the original text.
*/
private final void cancelNote() {
+
+ /*
+ * Tests to see that the original query operation didn't fail (see onCreate()). The Cursor
+ * object will exist, even if no records were returned, unless the query failed because of
+ * some exception or error.
+ */
if (mCursor != null) {
+
+ /*
+ * If the user is editing a note, and asked to discard or revert, this puts the
+ * previous note contents back into the note.
+ */
if (mState == STATE_EDIT) {
- // Put the original note text back into the database
+
+ // Closes the previous cursor prior to updating the provider
mCursor.close();
mCursor = null;
+
+ // Creates a new values map
ContentValues values = new ContentValues();
- values.put(Notes.NOTE, mOriginalContent);
- getContentResolver().update(mUri, values, null, null);
+
+ // Puts the original notes content into the values map. The variable was set in
+ // onResume().
+ values.put(NotePad.Notes.COLUMN_NAME_NOTE, mOriginalContent);
+
+ /*
+ * Update the provider with the reverted note content.
+ *
+ * Note: This is being done on the UI thread. It will block the thread until the
+ * update completes. In a sample app, going against a simple provider based on a
+ * local database, the block will be momentary, but in a real app you should use
+ * android.content.AsyncQueryHandler or android.os.AsyncTask.
+ */
+ getContentResolver().update(
+ mUri, // The URI of the note or notes.
+ values, // The reverted values to put into the provider.
+ null, // No selection criteria, so no where columns are needed.
+ null // No where columns are used, so no where values are needed.
+ );
+
+ /*
+ * If the user was inserting a note and decides to discard it, this deletes the note.
+ */
} else if (mState == STATE_INSERT) {
- // We inserted an empty note, make sure to delete it
+ // Deletes the note.
deleteNote();
}
}
+
+ // Returns a result of CANCELED to the calling Activity.
setResult(RESULT_CANCELED);
+
+ // Finishes the Activity. Once the user deletes or discards, nothing more can be done, so
+ // return to the calling Activity, either NotesList or some other Activity.
finish();
}
/**
- * Take care of deleting a note. Simply deletes the entry.
+ * This method deletes a note from the provider.
*/
private final void deleteNote() {
+ /*
+ * Tests to see that the original query operation didn't fail (see onCreate()). The Cursor
+ * object will exist, even if no records were returned, unless the query failed because of
+ * some exception or error.
+ */
if (mCursor != null) {
+
+ // Gets rid of all the Cursor's resources, and deactivates it.
mCursor.close();
mCursor = null;
- getContentResolver().delete(mUri, null, null);
+
+ /*
+ * Deletes the note based on the ID in the URI.
+ *
+ * Note: This is being done on the UI thread. It will block the thread until the
+ * delete completes. In a sample app, going against a simple provider based on a
+ * local database, the block will be momentary, but in a real app you should use
+ * android.content.AsyncQueryHandler android.os.AsyncTask.
+ */
+
+ getContentResolver().delete(
+ mUri, // The URI of the note to delete.
+ null, // No selection criteria are specified, so no where columns are needed.
+ null // No where columns are specified, so no where values are needed.
+ );
+
+ // Throws away any text currently showing in the View.
mText.setText("");
}
}