Home | History | Annotate | Download | only in notepad
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.example.android.notepad;
     18 
     19 import android.app.Activity;
     20 import android.content.ContentValues;
     21 import android.database.Cursor;
     22 import android.net.Uri;
     23 import android.os.Bundle;
     24 import android.text.TextUtils;
     25 import android.view.View;
     26 import android.widget.EditText;
     27 import android.widget.Toast;
     28 
     29 /**
     30  * This Activity allows the user to edit a note's title. It displays a floating window
     31  * containing an EditText.
     32  *
     33  * NOTE: Notice that the provider operations in this Activity are taking place on the UI thread.
     34  * This is not a good practice. It is only done here to make the code more readable. A real
     35  * application should use the {@link android.content.AsyncQueryHandler}
     36  * or {@link android.os.AsyncTask} object to perform operations asynchronously on a separate thread.
     37  */
     38 public class TitleEditor extends Activity {
     39 
     40     /**
     41      * This is a special intent action that means "edit the title of a note".
     42      */
     43     public static final String EDIT_TITLE_ACTION = "com.android.notepad.action.EDIT_TITLE";
     44 
     45     // Creates a projection that returns the note ID and the note contents.
     46     private static final String[] PROJECTION = new String[] {
     47             NotePad.Notes._ID, // 0
     48             NotePad.Notes.COLUMN_NAME_TITLE, // 1
     49     };
     50 
     51     // The position of the title column in a Cursor returned by the provider.
     52     private static final int COLUMN_INDEX_TITLE = 1;
     53 
     54     // An EditText object for preserving the edited title.
     55     private EditText mText;
     56 
     57     // A URI object for the note whose title is being edited.
     58     private Uri mUri;
     59 
     60     // The title that was last saved.
     61     private String mSavedTitle;
     62 
     63     /**
     64      * This method is called by Android when the Activity is first started. From the incoming
     65      * Intent, it determines what kind of editing is desired, and then does it.
     66      */
     67     @Override
     68     public void onCreate(Bundle savedInstanceState) {
     69         super.onCreate(savedInstanceState);
     70 
     71         // Set the View for this Activity object's UI.
     72         setContentView(R.layout.title_editor);
     73 
     74         // Gets the View ID for the EditText box
     75         mText = (EditText) this.findViewById(R.id.title);
     76 
     77         // Get the Intent that activated this Activity, and from it get the URI of the note whose
     78         // title we need to edit.
     79         mUri = getIntent().getData();
     80 
     81         /*
     82          * Using the URI passed in with the triggering Intent, gets the note.
     83          *
     84          * Note: This is being done on the UI thread. It will block the thread until the query
     85          * completes. In a sample app, going against a simple provider based on a local database,
     86          * the block will be momentary, but in a real app you should use
     87          * android.content.AsyncQueryHandler or android.os.AsyncTask.
     88          */
     89 
     90         Cursor cursor = getContentResolver().query(
     91             mUri,        // The URI for the note that is to be retrieved.
     92             PROJECTION,  // The columns to retrieve
     93             null,        // No selection criteria are used, so no where columns are needed.
     94             null,        // No where columns are used, so no where values are needed.
     95             null         // No sort order is needed.
     96         );
     97 
     98         if (cursor != null) {
     99 
    100             // The Cursor was just retrieved, so its index is set to one record *before* the first
    101             // record retrieved. This moves it to the first record.
    102             cursor.moveToFirst();
    103 
    104             // Displays the current title text in the EditText object.
    105             mText.setText(cursor.getString(COLUMN_INDEX_TITLE));
    106         }
    107     }
    108 
    109     /**
    110      * This method is called when the Activity is about to come to the foreground. This happens
    111      * when the Activity comes to the top of the task stack, OR when it is first starting.
    112      *
    113      * Displays the current title for the selected note.
    114      */
    115     @Override
    116     protected void onResume() {
    117         super.onResume();
    118     }
    119 
    120     /**
    121      * This method is called when the Activity loses focus.
    122      *
    123      * While there is no need to override this method in this app, it is shown here to highlight
    124      * that we are not saving any state in onPause, but have moved app state saving to onStop
    125      * callback.
    126      * In earlier versions of this app and popular literature it had been shown that onPause is good
    127      * place to persist any unsaved work, however, this is not really a good practice because of how
    128      * application and process lifecycle behave.
    129      * As a general guideline apps should have a way of saving their business logic that does not
    130      * solely rely on Activity (or other component) lifecyle state transitions.
    131      * As a backstop you should save any app state, not saved during lifetime of the Activity, in
    132      * onStop().
    133      * For a more detailed explanation of this recommendation please read
    134      * <a href = "https://developer.android.com/guide/topics/processes/process-lifecycle.html">
    135      * Processes and Application Life Cycle </a>.
    136      * <a href="https://developer.android.com/training/basics/activity-lifecycle/pausing.html">
    137      * Pausing and Resuming an Activity </a>.
    138      */
    139     @Override
    140     protected void onPause() {
    141         super.onPause();
    142     }
    143 
    144     /**
    145      * This method is called when the Activity becomes invisible.
    146      *
    147      * For Activity objects that edit information, onStop() may be the one place where changes are
    148      * saved.
    149      * Updates the note with the text currently in the text box.
    150      */
    151     @Override
    152     protected void onStop() {
    153         super.onStop();
    154         saveTitle();
    155     }
    156 
    157     public void onClickOk(View v) {
    158         saveTitle();
    159         finish();
    160     }
    161 
    162     // Saves the title if required
    163     private void saveTitle() {
    164 
    165         if (!TextUtils.isEmpty(mText.getText())) {
    166 
    167             String newTitle = mText.getText().toString();
    168 
    169             if (!newTitle.equals(mSavedTitle)) {
    170                 // Creates a values map for updating the provider.
    171                 ContentValues values = new ContentValues();
    172 
    173                 // In the values map, sets the title to the current contents of the edit box.
    174                 values.put(NotePad.Notes.COLUMN_NAME_TITLE, newTitle);
    175 
    176                 /*
    177                  * Updates the provider with the note's new title.
    178                  *
    179                  * Note: This is being done on the UI thread. It will block the thread until the
    180                  * update completes. In a sample app, going against a simple provider based on a
    181                  * local database, the block will be momentary, but in a real app you should use
    182                  * android.content.AsyncQueryHandler or android.os.AsyncTask.
    183                  */
    184                 getContentResolver().update(
    185                     mUri,    // The URI for the note to update.
    186                     values,
    187                     // The values map containing the columns to update and the values to use.
    188                     null,    // No selection criteria is used, so no "where" columns are needed.
    189                     null     // No "where" columns are used, so no "where" values are needed.
    190                 );
    191                 mSavedTitle = newTitle;
    192             }
    193         } else {
    194             Toast.makeText(this, R.string.title_blank, Toast.LENGTH_SHORT).show();
    195         }
    196     }
    197 }
    198