-
Notifications
You must be signed in to change notification settings - Fork 717
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,8 +15,12 @@ | |
*/ | ||
package com.example.android.pets; | ||
|
||
import android.app.LoaderManager; | ||
import android.content.ContentValues; | ||
import android.content.CursorLoader; | ||
import android.content.Intent; | ||
import android.content.Loader; | ||
import android.database.Cursor; | ||
import android.net.Uri; | ||
import android.os.Bundle; | ||
import android.support.v4.app.NavUtils; | ||
|
@@ -36,7 +40,14 @@ | |
/** | ||
* Allows user to create a new pet or edit an existing one. | ||
*/ | ||
public class EditorActivity extends AppCompatActivity { | ||
public class EditorActivity extends AppCompatActivity implements | ||
LoaderManager.LoaderCallbacks<Cursor> { | ||
|
||
/** Identifier for the pet data loader */ | ||
private static final int EXISTING_PET_LOADER = 0; | ||
|
||
/** 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; | ||
|
@@ -65,16 +76,20 @@ protected void onCreate(Bundle savedInstanceState) { | |
// Examine the intent that was used to launch this activity, | ||
// in order to figure out if we're creating a new pet or editing an existing one. | ||
Intent intent = getIntent(); | ||
Uri currentPetUri = intent.getData(); | ||
mCurrentPetUri = intent.getData(); | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
owolabiezekiel
|
||
|
||
// If the intent DOES NOT contain a pet content URI, then we know that we are | ||
// creating a new pet. | ||
if (currentPetUri == null) { | ||
if (mCurrentPetUri == null) { | ||
// This is a new pet, so change the app bar to say "Add a Pet" | ||
setTitle(getString(R.string.editor_activity_title_new_pet)); | ||
} else { | ||
// Otherwise this is an existing pet, so change app bar to say "Edit Pet" | ||
setTitle(getString(R.string.editor_activity_title_edit_pet)); | ||
|
||
// Initialize a loader to read the pet data from the database | ||
// and display the current values in the editor | ||
getLoaderManager().initLoader(EXISTING_PET_LOADER, null, this); | ||
This comment has been minimized.
Sorry, something went wrong.
chrisjeremi98
|
||
} | ||
|
||
// Find all relevant views that we will need to read user input from | ||
|
@@ -190,4 +205,77 @@ public boolean onOptionsItemSelected(MenuItem item) { | |
} | ||
return super.onOptionsItemSelected(item); | ||
} | ||
|
||
@Override | ||
public Loader<Cursor> onCreateLoader(int i, 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 comment has been minimized.
Sorry, something went wrong.
alexejmamaev
|
||
// This loader will execute the ContentProvider's query method on a background thread | ||
return new CursorLoader(this, // Parent activity context | ||
mCurrentPetUri, // Query the content URI for the current pet | ||
This comment has been minimized.
Sorry, something went wrong.
atarancon
|
||
projection, // Columns to include in the resulting Cursor | ||
null, // No selection clause | ||
null, // No selection arguments | ||
null); // Default sort order | ||
} | ||
|
||
@Override | ||
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { | ||
// Bail early if the cursor is null or there is less than 1 row in the cursor | ||
if (cursor == null || cursor.getCount() < 1) { | ||
return; | ||
} | ||
|
||
// Proceed with moving to the first row of the cursor and reading data from it | ||
// (This should be the only row in the cursor) | ||
if (cursor.moveToFirst()) { | ||
This comment has been minimized.
Sorry, something went wrong.
karkinissan
|
||
// 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); | ||
|
||
// Update the views on the screen with the values from the database | ||
mNameEditText.setText(name); | ||
mBreedEditText.setText(breed); | ||
mWeightEditText.setText(Integer.toString(weight)); | ||
|
||
// Gender is a dropdown spinner, so map the constant value from the database | ||
// into one of the dropdown options (0 is Unknown, 1 is Male, 2 is Female). | ||
// Then call setSelection() so that option is displayed on screen as the current selection. | ||
switch (gender) { | ||
case PetEntry.GENDER_MALE: | ||
This comment has been minimized.
Sorry, something went wrong.
jensgreiner
|
||
mGenderSpinner.setSelection(1); | ||
break; | ||
case PetEntry.GENDER_FEMALE: | ||
mGenderSpinner.setSelection(2); | ||
break; | ||
default: | ||
mGenderSpinner.setSelection(0); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public void onLoaderReset(Loader<Cursor> loader) { | ||
// If the loader is invalidated, clear out all the data from the input fields. | ||
mNameEditText.setText(""); | ||
mBreedEditText.setText(""); | ||
mWeightEditText.setText(""); | ||
mGenderSpinner.setSelection(0); // Select "Unknown" gender | ||
} | ||
} |
27 comments
on commit 8d4b875
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The solution code here is a little different from the one in the classroom answer, like the onLoaderReset() body and the first two lines from onLoadFinish() are missing!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add new pet was causing a crash after making these code changes. It turns out you need to check if mCurrentPetUri is null and return null from onCreateLoader if it is.
@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
if (mCurrentPetUri == null) {
return null;
}
// Since the editor shows all pet attributes, define a projection that contains
// all columns from the pet table
String[] projection = {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On line 220, when we're creating a new CursorLoader
, I don't understand why we're loading all Pet data into EditorActivity when we will ever only need a single Pet
data. Shouldn't we set the selection
and selectionArgs
for a single Pet
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're not. Notice how we pass mCurrentPetUri in on line 222. So that is only querying the name, breed, gender and weight for that specific pet Uri which includes the pet _ID that was passed in from the main activity. The actual query would look something like
SELECT name, breed, gender, weight FROM pets WHERE _ID = 5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @linucksrox . I see, I was getting and setting the selection
and selectionArgs
but the solution's method is much better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@linucksrox in your code:
@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
if (mCurrentPetUri == null) {
return null;
}
// Since the editor shows all pet attributes, define a projection that contains
// all columns from the pet table
String[] projection = {
When you return null
, does that:
- Exit us out of
onCreateLoader()
- Essentially no
CursorLoader
is created so thenEditorActivity
defaults to not filling the text fields
I encountered the same problem and just want to understand the solution in case I run into it next time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Yes, any return statement will exit out of that method
- Correct, no
CursorLoader
is created because there's nothing to query.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One way is to use a global variable for URI of the item, another way is to put the id part of the URI into a Bundle object and set it in the initLoader
call. Within onCreateLoader(...)
the Bundle data is retrieved and the URI is build again using ContentUris.appendedWithId()
. Is a bit more complicated but works as designed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One way is to use a global variable for URI of the item
Well, it seems in one of the very next steps this global variable path will be used for another reason too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add new pet was causing a crash after making these code changes. It turns out you need to check if mCurrentPetUri is null and return null from onCreateLoader if it is.
When you add a new pet, the Loader should not be initialized if you use this code in the onCreate in the EditorActivity.
`
Intent intent = getIntent();
mCurrentPetUri = intent.getData();
if (mCurrentPetUri == null) {
setTitle(getString(R.string.editor_activity_title_new_pet));
} else {
setTitle(getString(R.string.editor_activity_title_edit_pet));
getLoaderManager().initLoader(EXISTING_PET_LOADER, null, this);
}
`
Therefore, you don't need to use your code in the OnCreateLoader.
It's less expensive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Wolf2231 Yes, I tested that change and it worked as expected. It makes more sense than what I originally said. Thanks for the update!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MrEremka use getSupportLoaderManager(); instead getLoaderManager();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Im getting this error whenever i click a pet:
12-14 12:12:37.647 32358-32433/com.example.android.pets E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #2
Process: com.example.android.pets, PID: 32358
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:309)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.NullPointerException: uri
at com.android.internal.util.Preconditions.checkNotNull(Preconditions.java:60)
at android.content.ContentResolver.query(ContentResolver.java:474)
at android.content.CursorLoader.loadInBackground(CursorLoader.java:64)
at android.content.CursorLoader.loadInBackground(CursorLoader.java:56)
at android.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:312)
at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:69)
at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:66)
at android.os.AsyncTask$2.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was also getting the same error when i click a pet.
help required!!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change this line in the PetProvider Class in the static { ------ } sUriMatcher.addURI(PetContract.CONTENT_AUTHORITY,PetContract.PATH_PETS+"#",PET_ID);
to
sUriMatcher.addURI(PetContract.CONTENT_AUTHORITY,PetContract.PATH_PETS+"/#",PET_ID);
had resolved the issue for me
@ShahoodulHassan may be this is kind of the mistake in your code too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So far so good 👍 Except when we save the edited pet we actually add a new one instead of replacing the existing pet but I'm pretty sure we will fix that soon..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe that we'd have cleaner code by using anonymous classes for implementing the callbacks instead of doing that..(Keep in mind that if you use this you cant have 2 loaders in the same activity 👎 )
Also, we don't need a projection array in onCreateLoader method because we can pass null(which by default will have the same results 👍 )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does it do this? It stops my app from working and I don't understand why.
And yes I have implemented LoaderManager.LoaderCallbacks in the proper way
public class EditorActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks
Update your import:
import android.app.LoaderManager;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
Add all other relevant imports. Its mentioned in tutorial 6 that imports are wrong and need to be updated with right one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getSupportLoaderManager().initLoader(EXISTING_PET_LOADER, null, this);
App still crashes... please help !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change this line in the PetProvider Class in the static { ------ } sUriMatcher.addURI(PetContract.CONTENT_AUTHORITY,PetContract.PATH_PETS+"#",PET_ID);
to
sUriMatcher.addURI(PetContract.CONTENT_AUTHORITY,PetContract.PATH_PETS+"/#",PET_ID);
had resolved the issue for me
@ShahoodulHassan may be this is kind of the mistake in your code too.
bro, thank you a lot !!!!!!! you eased my life after 3 days debugging this code.... I was giving up the rest of the course
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2020-06-21 22:26:02.726 18477-18477/com.example.android.pets E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.pets, PID: 18477
android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1
at android.database.AbstractCursor.checkPosition(AbstractCursor.java:460)
at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50)
at android.database.CursorWrapper.getString(CursorWrapper.java:137)
at com.example.android.pets.EditorActivity.onLoadFinished(EditorActivity.java:253)
at com.example.android.pets.EditorActivity.onLoadFinished(EditorActivity.java:57)
at androidx.loader.app.LoaderManagerImpl$LoaderObserver.onChanged(LoaderManagerImpl.java:250)
at androidx.lifecycle.LiveData.considerNotify(LiveData.java:113)
at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:131)
at androidx.lifecycle.LiveData.setValue(LiveData.java:289)
at androidx.lifecycle.MutableLiveData.setValue(MutableLiveData.java:33)
at androidx.loader.app.LoaderManagerImpl$LoaderInfo.setValue(LoaderManagerImpl.java:189)
at androidx.loader.app.LoaderManagerImpl$LoaderInfo.onLoadComplete(LoaderManagerImpl.java:174)
at androidx.loader.content.Loader.deliverResult(Loader.java:132)
I have been doing all the steps same as tutorial, but I am getting this error, tried to fix but I cant find any solution, if smn knows the solution, help is apreciated)) Thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2020-06-21 22:26:02.726 18477-18477/com.example.android.pets E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.pets, PID: 18477
android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1
at android.database.AbstractCursor.checkPosition(AbstractCursor.java:460)
at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50)
at android.database.CursorWrapper.getString(CursorWrapper.java:137)
at com.example.android.pets.EditorActivity.onLoadFinished(EditorActivity.java:253)
at com.example.android.pets.EditorActivity.onLoadFinished(EditorActivity.java:57)
at androidx.loader.app.LoaderManagerImpl$LoaderObserver.onChanged(LoaderManagerImpl.java:250)
at androidx.lifecycle.LiveData.considerNotify(LiveData.java:113)
at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:131)
at androidx.lifecycle.LiveData.setValue(LiveData.java:289)
at androidx.lifecycle.MutableLiveData.setValue(MutableLiveData.java:33)
at androidx.loader.app.LoaderManagerImpl$LoaderInfo.setValue(LoaderManagerImpl.java:189)
at androidx.loader.app.LoaderManagerImpl$LoaderInfo.onLoadComplete(LoaderManagerImpl.java:174)
at androidx.loader.content.Loader.deliverResult(Loader.java:132)I have been doing all the steps same as tutorial, but I am getting this error, tried to fix but I cant find any solution, if smn knows the solution, help is apreciated)) Thanks
Please describe properly the problem to help us help you. I've finished this course there is one week now. I got lot of problem too but I solved them all
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2020-07-19 13:55:39.504 31728-31728/com.example.android.pets E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.pets, PID: 31728
java.lang.IllegalStateException: ** ### ### Couldn't read row 0, col -1 from CursorWindow**. Make sure the Cursor is initialized correctly before accessing data from it.
at android.database.CursorWindow.nativeGetLong(Native Method)
at android.database.CursorWindow.getLong(CursorWindow.java:538)
at android.database.CursorWindow.getInt(CursorWindow.java:605)
at android.database.AbstractWindowedCursor.getInt(AbstractWindowedCursor.java:69)
at android.database.CursorWrapper.getInt(CursorWrapper.java:122)
at com.example.android.pets.EditorActivity.onLoadFinished(EditorActivity.java:250)
at com.example.android.pets.EditorActivity.onLoadFinished(EditorActivity.java:43)
at android.app.LoaderManagerImpl$LoaderInfo.callOnLoadFinished(LoaderManager.java:497)
at android.app.LoaderManagerImpl$LoaderInfo.onLoadComplete(LoaderManager.java:465)
at android.content.Loader.deliverResult(Loader.java:157)
at android.content.CursorLoader.deliverResult(CursorLoader.java:113)
at android.content.CursorLoader.deliverResult(CursorLoader.java:45)
at android.content.AsyncTaskLoader.dispatchOnLoadComplete(AsyncTaskLoader.java:272)
at android.content.AsyncTaskLoader$LoadTask.onPostExecute(AsyncTaskLoader.java:96)
at android.os.AsyncTask.finish(AsyncTask.java:695)
at android.os.AsyncTask.access$600(AsyncTask.java:180)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:712)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:227)
at android.app.ActivityThread.main(ActivityThread.java:7212)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:575)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:887)
I don't know why is this happening
In my senses,I've done everything as required
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is my complete state of the code.
`import android.app.LoaderManager;
import android.content.ContentValues;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
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 androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NavUtils;
import com.example.petapp.data.PetContract.PetEntry;
import static com.example.petapp.data.PetContract.BASE_CONTENT_URI;
import static com.example.petapp.data.PetContract.PATH_PETS;
public class EditorActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks {
/** Identifier for the pet data loader */
private static final int EXISTING_PET_LOADER = 0;
/** Content URI for the existing pet (null if it's a new pet) */
private Uri mCurrentPetUri;
public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, PATH_PETS);
/**
* EditText field to enter the pet's name, breed and weight....
*/
private EditText mNameEditText, mBreedEditText,mWeightEditText;
private Spinner mGenderSpinner;
/**
* Gender of the pet. The possible values are:
* 0 for unknown gender, 1 for male, 2 for female.
*/
private int mGender = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_editor);
Intent intent = getIntent();
mCurrentPetUri = intent.getData();
if(mCurrentPetUri == null){
setTitle(getString(R.string.add_pet));
}else{
// Otherwise this is an existing pet, so change app bar to say "Edit Pet"
setTitle(getString(R.string.edit_pet));
// Initialize a loader to read the pet data from the database
// and display the current values in the editor
getLoaderManager().initLoader(EXISTING_PET_LOADER, null, this);
}
// Find all relevant views that we will need to read user input from
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();
}
/**
* 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 = PetEntry.GENDER_UNKNOWN; // Unknown
}
});
}
/**
* Get user input from editor and save new pet into database.
* Here, the flow of the execution of the insert method is like this
* EditorActivity-> ContentResolver -> PetProvider(UriMatcher) -> insert a new pet or perform a update on the single pet
* After that PetProvider(UriMatcher) -> ContentResolver -> EditorActivity (returns a new Uri object )
*/
private void insertPet() {
// Read from input fields
// Use trim to eliminate leading or trailing white space
String nameString = mNameEditText.getText().toString().trim();
String breedString = mBreedEditText.getText().toString().trim();
String weightString = mWeightEditText.getText().toString().trim();
int weight = Integer.parseInt(weightString);
// Create a ContentValues object where column names are the keys,
// and pet attributes from the editor are the values.
ContentValues values = new ContentValues();
values.put(PetEntry.COLUMN_PET_NAME, nameString);
values.put(PetEntry.COLUMN_PET_BREED, breedString);
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.pet_saved),
Toast.LENGTH_SHORT).show();
} else {
// Otherwise, the insertion was successful and we can display a toast.
Toast.makeText(this, getString(R.string.not_saved),
Toast.LENGTH_SHORT).show();
}
}
@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:
// save the data the has entered
insertPet();
//after the save has done the finish() method takes us to the CatalogActivity
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 i, 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
mCurrentPetUri, // 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(Loader<Cursor> loader, Cursor cursor) {
// Bail early if the cursor is null or there is less than 1 row in the cursor
if (cursor == null || cursor.getCount() < 1) {
return;
}
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);
// Update the views on the screen with the values from the database
mNameEditText.setText(name);
mBreedEditText.setText(breed);
mWeightEditText.setText(Integer.toString(weight));
mGenderSpinner.setSelection(gender);
}
}
@Override
public void onLoaderReset( Loader<Cursor> loader) {
// If the loader is invalidated, clear out all the data from the input fields.
mNameEditText.setText("");
mBreedEditText.setText("");
mWeightEditText.setText("");
mGenderSpinner.setSelection(0); // Select "Unknown" gender
}
}`
I have problem in this line of code. My code won't work because the query which this URI makes, is not valid. Instead I've written this code: (uri = mCurrentPetUri in my code)
@OverRide
public Loader onCreateLoader(int id, Bundle args) {
uri = getIntent().getData();
String selection = PetEntry._ID+ "=?";
String[] selectionArgs = new String[]{String.valueOf(ContentUris.parseId(uri))};
String[] projection = {
PetEntry._ID,
PetEntry.COLUMN_PET_NAME,
PetEntry.COLUMN_PET_BREED,
PetEntry.COLUMN_PET_GENDER,
PetEntry.COLUMN_PET_WEIGHT };
CursorLoader loader = new CursorLoader(this, PetEntry.CONTENT_URI, projection, selection,selectionArgs , null);
return loader;
}
Why mCurrentPetUri does not works?