Skip to content

Commit

Permalink
1.23 Save changes to existing pet if it already exists
Browse files Browse the repository at this point in the history
  • Loading branch information
Beginning Android committed Aug 23, 2016
1 parent 8d4b875 commit 20d0524
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 14 deletions.
49 changes: 35 additions & 14 deletions app/src/main/java/com/example/android/pets/EditorActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,9 @@ public void onNothingSelected(AdapterView<?> parent) {
}

/**
* Get user input from editor and save new pet into database.
* Get user input from editor and save pet into database.
*/
private void insertPet() {
private void savePet() {
// Read from input fields
// Use trim to eliminate leading or trailing white space
String nameString = mNameEditText.getText().toString().trim();
Expand All @@ -159,18 +159,39 @@ private void insertPet() {
values.put(PetEntry.COLUMN_PET_GENDER, mGender);
values.put(PetEntry.COLUMN_PET_WEIGHT, weight);

// Insert a new pet into the provider, returning the content URI for the new pet.
Uri newUri = getContentResolver().insert(PetEntry.CONTENT_URI, values);

// Show a toast message depending on whether or not the insertion was successful
if (newUri == null) {
// If the new content URI is null, then there was an error with insertion.
Toast.makeText(this, getString(R.string.editor_insert_pet_failed),
Toast.LENGTH_SHORT).show();
// Determine if this is a new or existing pet by checking if mCurrentPetUri is null or not
if (mCurrentPetUri == null) {
// This is a NEW pet, so insert a new pet into the provider,
// returning the content URI for the new pet.
Uri newUri = getContentResolver().insert(PetEntry.CONTENT_URI, values);

// Show a toast message depending on whether or not the insertion was successful.
if (newUri == null) {
// If the new content URI is null, then there was an error with insertion.
Toast.makeText(this, getString(R.string.editor_insert_pet_failed),
Toast.LENGTH_SHORT).show();
} else {
// Otherwise, the insertion was successful and we can display a toast.
Toast.makeText(this, getString(R.string.editor_insert_pet_successful),
Toast.LENGTH_SHORT).show();
}
} else {
// Otherwise, the insertion was successful and we can display a toast.
Toast.makeText(this, getString(R.string.editor_insert_pet_successful),
Toast.LENGTH_SHORT).show();
// Otherwise this is an EXISTING pet, so update the pet with content URI: mCurrentPetUri
// and pass in the new ContentValues. Pass in null for the selection and selection args
// because mCurrentPetUri will already identify the correct row in the database that
// we want to modify.
int rowsAffected = getContentResolver().update(mCurrentPetUri, values, null, null);

// Show a toast message depending on whether or not the update was successful.
if (rowsAffected == 0) {
// If no rows were affected, then there was an error with the update.
Toast.makeText(this, getString(R.string.editor_update_pet_failed),
Toast.LENGTH_SHORT).show();
} else {
// Otherwise, the update was successful and we can display a toast.
Toast.makeText(this, getString(R.string.editor_update_pet_successful),
Toast.LENGTH_SHORT).show();
}
}
}

Expand All @@ -189,7 +210,7 @@ public boolean onOptionsItemSelected(MenuItem item) {
// Respond to a click on the "Save" menu option
case R.id.action_save:
// Save pet to database
insertPet();
savePet();
// Exit activity
finish();
return true;
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@
<!-- Toast message in editor when new pet has failed to be inserted [CHAR LIMIT=NONE] -->
<string name="editor_insert_pet_failed">Error with saving pet</string>

<!-- Toast message in editor when current pet was successfully updated [CHAR LIMIT=NONE] -->
<string name="editor_update_pet_successful">Pet updated</string>

<!-- Toast message in editor when current pet has failed to be updated [CHAR LIMIT=NONE] -->
<string name="editor_update_pet_failed">Error with updating pet</string>

<!-- Label for overview category of attributes in the editor [CHAR LIMIT=30] -->
<string name="category_overview">Overview</string>

Expand Down

13 comments on commit 20d0524

@Smarpit-Singh
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Working well.

@AcidTEX
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everytime I want to update a pet, the app seems to process a few seconds and then gets back to the Catalog without having any changes made. Also no toast message was shown.
I double checked the code here. I think there must be something wrong with the update method?

@shanudjn
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when i click on the save button after editing a pet the app stops. What might be the problem behind that?

@sherifhisham
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

successful work

@sherifhisham
Copy link

@sherifhisham sherifhisham commented on 20d0524 May 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shanudjn maybe you deleted codes of Uri newUri = getContentResolver().insert(PetEntry.CONTENT_URI, values);

  •    // Show a toast message depending on whether or not the insertion was successful
    
  •    if (newUri == null) {
    
  •        // If the new content URI is null, then there was an error with insertion.
    
  •        Toast.makeText(this, getString(R.string.editor_insert_pet_failed),
    
  •                Toast.LENGTH_SHORT).show(); 
    

and Toast.makeText(this, getString(R.string.editor_insert_pet_successful),

  •                Toast.LENGTH_SHORT).show(); 
    

@J0k3R101
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the list view not updated when i get back from UPDATE mode while add mode list updated well!
can tell what i miss here, and where to add it?

@Babadzhanov
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@J0k3R101 the issue lies within updatePet() method.. in the very bottom just before the return statement add this snippet if you don't have it already:

    if (rowsUpdated != 0) {
        getContext().getContentResolver().notifyChange(uri, null);
    }

@J0k3R101
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maginom , Thank you
i got another question, i was trying to apply a search filter through EditText on the ListView result to target a specific pet but didn't work at all, have you tried anything like that, or help me out?

@BasemSaabneh
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice work

@RajeetGoyal
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when I click on the save button after editing a pet the app stops. What might be the problem behind that?

@shanudjn There might be an error in your PetProvider class. If you are unable to find it, then compare your PetProvider class with the official one.

@priyangshupal
Copy link

@priyangshupal priyangshupal commented on 20d0524 Jun 15, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My code is showing NullPointerException at this line:
Uri currentPetUri = intent.getData();

Plz help..

My Editor Activity Code:
package com.example.pets;

import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.LoaderManager;
import android.support.v4.app.NavUtils;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;

import com.example.pets.data.PetContract.PetEntry;

/**

  • Allows user to create a new pet or edit an existing one.
    */
    public class EditorActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks {

    Uri currentPetUri;

    /**

    • Content URI for the existing pet (null if it's a new pet)
      */
      // private Uri mCurrentPetUri;

    /**

    • EditText field to enter the pet's name
      */
      private EditText mNameEditText;

    /**

    • EditText field to enter the pet's breed
      */
      private EditText mBreedEditText;

    /**

    • EditText field to enter the pet's weight
      */
      private EditText mWeightEditText;

    /**

    • EditText field to enter the pet's gender
      */
      private Spinner mGenderSpinner;
      private int mGender = 0;

    @OverRide
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_editor);

     android.support.v4.app.LoaderManager loaderManager = getSupportLoaderManager();
    
     loaderManager.initLoader(0, null, this);
    
    
     Intent intent = getIntent();
     currentPetUri = intent.getData();
    
     if (currentPetUri == null) {
         setTitle(R.string.no_uri_title);
     } else {
         setTitle(R.string.uri_title);
     }
    
     mNameEditText = findViewById(R.id.edit_pet_name);
     mBreedEditText = findViewById(R.id.edit_pet_breed);
     mWeightEditText = findViewById(R.id.edit_pet_weight);
     mGenderSpinner = findViewById(R.id.spinner_gender);
    
     setupSpinner();
    

// android.support.v4.app.LoaderManager loaderManager = getSupportLoaderManager();
//
// loaderManager.initLoader(0, null, this);
}

/**
 * Setup the dropdown spinner that allows the user to select the gender of the pet.
 */
private void setupSpinner() {
    // Create adapter for spinner. The list options are from the String array it will use
    // the spinner will use the default layout
    ArrayAdapter genderSpinnerAdapter = ArrayAdapter.createFromResource(this,
            R.array.array_gender_options, android.R.layout.simple_spinner_item);

    // Specify dropdown layout style - simple list view with 1 item per line
    genderSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);

    // Apply the adapter to the spinner
    mGenderSpinner.setAdapter(genderSpinnerAdapter);

    // Set the integer mSelected to the constant values
    mGenderSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            String selection = (String) parent.getItemAtPosition(position);
            if (!TextUtils.isEmpty(selection)) {
                if (selection.equals(getString(R.string.gender_male))) {
                    mGender = PetEntry.GENDER_MALE; // Male
                } else if (selection.equals(getString(R.string.gender_female))) {
                    mGender = PetEntry.GENDER_FEMALE; // Female
                } else {
                    mGender = PetEntry.GENDER_UNKNOWN; // Unknown
                }
            }
        }

        // Because AdapterView is an abstract class, onNothingSelected must be defined
        @Override
        public void onNothingSelected(AdapterView<?> parent) {
            mGender = 0; // Unknown
        }
    });
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu options from the res/menu/menu_editor.xml file.
    // This adds menu items to the app bar.
    getMenuInflater().inflate(R.menu.menu_editor, 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 "Save" menu option
        case R.id.action_save:
            savePet();
            finish();
            return true;
        // Respond to a click on the "Delete" menu option
        case R.id.action_delete:
            // Do nothing for now
            return true;
        // Respond to a click on the "Up" arrow button in the app bar
        case android.R.id.home:
            // Navigate back to parent activity (CatalogActivity)
            NavUtils.navigateUpFromSameTask(this);
            return true;
    }
    return super.onOptionsItemSelected(item);
}

private void savePet() {
    String pet_name = mNameEditText.getText().toString();
    String pet_breed = mBreedEditText.getText().toString();
    int pet_weight = Integer.parseInt(mWeightEditText.getText().toString());

    ContentValues values = new ContentValues();
    values.put(PetEntry.COLUMN_PET_NAME, pet_name);
    values.put(PetEntry.COLUMN_PET_BREED, pet_breed);
    values.put(PetEntry.COLUMN_PET_GENDER, mGender);
    values.put(PetEntry.COLUMN_PET_WEIGHT, pet_weight);

    getContentResolver().insert(PetEntry.CONTENT_URI, values);

// if (mCurrentPetUri == null) {
// // This is a NEW pet, so insert a new pet into the provider,
// // returning the content URI for the new pet.
// Uri newUri = getContentResolver().insert(PetEntry.CONTENT_URI, values);
//
// // Show a toast message depending on whether or not the insertion was successful.
// if (newUri == null) {
// // If the new content URI is null, then there was an error with insertion.
// Toast.makeText(this, getString(R.string.editor_insert_pet_failed),
// Toast.LENGTH_SHORT).show();
// } else {
// // Otherwise, the insertion was successful and we can display a toast.
// Toast.makeText(this, getString(R.string.editor_insert_pet_successful),
// Toast.LENGTH_SHORT).show();
// }
// } else {
// // Otherwise this is an EXISTING pet, so update the pet with content URI: mCurrentPetUri
// // and pass in the new ContentValues. Pass in null for the selection and selection args
// // because mCurrentPetUri will already identify the correct row in the database that
// // we want to modify.
// int rowsAffected = getContentResolver().update(mCurrentPetUri, values, null, null);
//
// // Show a toast message depending on whether or not the update was successful.
// if (rowsAffected == 0) {
// // If no rows were affected, then there was an error with the update.
// Toast.makeText(this, getString(R.string.editor_update_pet_failed),
// Toast.LENGTH_SHORT).show();
// } else {
// // Otherwise, the update was successful and we can display a toast.
// Toast.makeText(this, getString(R.string.editor_update_pet_successful),
// Toast.LENGTH_SHORT).show();
// }
// }
}

@NonNull
@Override
public Loader<Cursor> onCreateLoader(int i, @Nullable Bundle bundle) {
    // Since the editor shows all pet attributes, define a projection that contains
    // all columns from the pet table
    String[] projection = {
            PetEntry._ID,
            PetEntry.COLUMN_PET_NAME,
            PetEntry.COLUMN_PET_BREED,
            PetEntry.COLUMN_PET_GENDER,
            PetEntry.COLUMN_PET_WEIGHT};

    // This loader will execute the ContentProvider's query method on a background thread
    return new CursorLoader(this,   // Parent activity context
            currentPetUri,         // Query the content URI for the current pet
            projection,             // Columns to include in the resulting Cursor
            null,                   // No selection clause
            null,                   // No selection arguments
            null);                  // Default sort order
}


@Override
public void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor cursor) {

    if (cursor.moveToFirst()) {
        // Find the columns of pet attributes that we're interested in
        int nameColumnIndex = cursor.getColumnIndex(PetEntry.COLUMN_PET_NAME);
        int breedColumnIndex = cursor.getColumnIndex(PetEntry.COLUMN_PET_BREED);
        int genderColumnIndex = cursor.getColumnIndex(PetEntry.COLUMN_PET_GENDER);
        int weightColumnIndex = cursor.getColumnIndex(PetEntry.COLUMN_PET_WEIGHT);

        // Extract out the value from the Cursor for the given column index
        String name = cursor.getString(nameColumnIndex);
        String breed = cursor.getString(breedColumnIndex);
        int gender = cursor.getInt(genderColumnIndex);
        int weight = cursor.getInt(weightColumnIndex);

        mNameEditText.setText(name);
        mBreedEditText.setText(breed);
        mWeightEditText.setText(Integer.toString(weight));

        switch (gender) {
            case PetEntry.GENDER_MALE:
                mGenderSpinner.setSelection(1);
                break;
            case PetEntry.GENDER_FEMALE:
                mGenderSpinner.setSelection(2);
                break;
            default:
                mGenderSpinner.setSelection(0);
                break;
        }
    }
}

@Override
public void onLoaderReset(@NonNull Loader<Cursor> loader) {

}

}

@SherifSalem
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when i try to update the values , and click the save button the app crashes
and it throws an exception for invalid pet gender
when i ran the debugger the values i changed shows except for the gender it shows this value "gender" -> "2131230845"
this is the code for my editor activity
public class EditorActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks {

/** EditText field to enter the pet's name */
private EditText mNameEditText;

/** EditText field to enter the pet's breed */
private EditText mBreedEditText;

/** EditText field to enter the pet's weight */
private EditText mWeightEditText;

/** EditText field to enter the pet's gender */
private Spinner mGenderSpinner;

private Uri petUri;

/**
 * Gender of the pet. The possible values are:
 * 0 for unknown gender, 1 for male, 2 for female.
 */
private int mGender = 0;

//instance variable of the database helpr class
private PetsDbHelper helper;

public static final int LOADER_ID = 1008;

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

    //instantiate the database helper class
    helper = new PetsDbHelper(this);





    // Find all relevant views that we will need to read user input from
    mNameEditText = (EditText) findViewById(R.id.edit_pet_name);
    mBreedEditText = (EditText) findViewById(R.id.edit_pet_breed);
    mWeightEditText = (EditText) findViewById(R.id.edit_pet_weight);
    mGenderSpinner = (Spinner) findViewById(R.id.spinner_gender);

    setupSpinner();

    petUri = getIntent().getData();

// check whether if the intent either for adding new pet or edit existing pet
if (petUri == null ){

        setTitle(getString(R.string.editor_activity_title_new_pet));

    }else
    {
        setTitle(getString(R.string.editor_activity_title_edit_pet));
    }

    getLoaderManager().initLoader(LOADER_ID, null, this);





}

/**
 * Setup the dropdown spinner that allows the user to select the gender of the pet.
 */
private void setupSpinner() {
    // Create adapter for spinner. The list options are from the String array it will use
    // the spinner will use the default layout
    ArrayAdapter genderSpinnerAdapter = ArrayAdapter.createFromResource(this,
            R.array.array_gender_options, android.R.layout.simple_spinner_item);

    // Specify dropdown layout style - simple list view with 1 item per line
    genderSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);

    // Apply the adapter to the spinner
    mGenderSpinner.setAdapter(genderSpinnerAdapter);

    // Set the integer mSelected to the constant values
    mGenderSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            String selection = (String) parent.getItemAtPosition(position);

            if (!TextUtils.isEmpty(selection)) {

                if (selection.equals(getString(R.string.gender_male))) {
                    mGender = PetsEntry.GENDER_MALE; // Male
                } else if (selection.equals(getString(R.string.gender_female))) {
                    mGender = PetsEntry.GENDER_FEMALE; // Female
                } else {
                    mGender = PetsEntry.GENDER_UNKOWN; // Unknown
                }
            }
        }

        // Because AdapterView is an abstract class, onNothingSelected must be defined
        @Override
        public void onNothingSelected(AdapterView<?> parent) {
            mGender = 0; // Unknown
        }
    });
}

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


//save new entered pet
private void savePet(){
    //get the values entered by the user for the pet
    String petName = mNameEditText.getText().toString().trim();
    String petBreed = mBreedEditText.getText().toString().trim();
    int gender = mGenderSpinner.getId();
    int weight = Integer.parseInt(mWeightEditText.getText().toString().trim());



    //put the value of the pet's information into a content value
    ContentValues values = new ContentValues();
    values.put(PetsEntry.PET_NAME,petName);
    values.put(PetsEntry.PET_BREED,petBreed);
    values.put(PetsEntry.PET_GENDER,gender);
    values.put(PetsEntry.PET_WEIGHT,weight);

    if (petUri == null) {

        Uri newUri = getContentResolver().insert(PetsEntry.CONTENT_URI, values);

        if (newUri == null){

            Toast.makeText(this, getString(R.string.failed_to_save_pet), Toast.LENGTH_SHORT).show();
        }
        else
            {
            Toast.makeText(this, getString(R.string.pet_saved)+ newUri, Toast.LENGTH_SHORT).show();
        }
    }
    else
        {

      int updatedrows = getContentResolver().update(petUri,values,null,null);

        Toast.makeText(this, "Pet updated" + " " + updatedrows, Toast.LENGTH_SHORT).show();
        if (updatedrows == 0)
        {
            Toast.makeText(this, getString(R.string.failed_to_update_pet), Toast.LENGTH_SHORT).show();
        }
        else
            {
           Toast.makeText(this, getString(R.string.pet_updated)+ updatedrows, Toast.LENGTH_SHORT).show();
        }
    }
    //long rowId = db.insert(PetsEntry.PETS_TABLE_NAME,null,values);



}

@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 "Save" menu option
        case R.id.action_save:
            savePet();
            finish();
            return true;
        // Respond to a click on the "Delete" menu option
        case R.id.action_delete:
            // Do nothing for now
            return true;
        // Respond to a click on the "Up" arrow button in the app bar
        case android.R.id.home:
            // Navigate back to parent activity (CatalogActivity)
            NavUtils.navigateUpFromSameTask(this);
            return true;
    }
    return super.onOptionsItemSelected(item);
}

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
  String[] projection = {
          PetsEntry.PET_ID,
          PetsEntry.PET_NAME,
          PetsEntry.PET_BREED,
          PetsEntry.PET_GENDER,
          PetsEntry.PET_WEIGHT
  };

    return new CursorLoader(this,
            petUri,
            projection,
            null,
            null,
            null);
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {


   if (cursor.moveToFirst()) {
       int nameColumnIndex = cursor.getColumnIndex(PetsEntry.PET_NAME);
       int breedColumnIndex = cursor.getColumnIndex(PetsEntry.PET_BREED);
       int genderColumnIndex = cursor.getColumnIndex(PetsEntry.PET_GENDER);
       int weightColumnIndex = cursor.getColumnIndex(PetsEntry.PET_WEIGHT);


       String name = cursor.getString(nameColumnIndex);
       String breed = cursor.getString(breedColumnIndex);
       int gender = cursor.getInt(genderColumnIndex);
       int weight = cursor.getInt(weightColumnIndex);
       Log.d("OnLoad finish", Integer.toString(gender));
       mNameEditText.setText(name);
       mBreedEditText.setText(breed);
       mWeightEditText.setText(Integer.toString(weight));

       switch (gender){
           case PetsEntry.GENDER_MALE:
               mGenderSpinner.setSelection(1);
               break;
               case PetsEntry.GENDER_FEMALE:
                   mGenderSpinner.setSelection(2);
                   break;
                   default:
                       mGenderSpinner.setSelection(0);

       }
   }
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {

    loader.reset();

}

}

@CashatSD2020
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everytime I want to update a pet, the app seems to process a few seconds and then gets back to the Catalog without having any changes made. Also no toast message was shown.
I double checked the code here. I think there must be something wrong with the update method?

check savePet() method , specially the if else

Please sign in to comment.