Reading List is an application that lets you save a list of books and allow you to mark whether you have or have not read them. Since this application will use persistence, the books you create and check as read or not will be saved between launches of the application.
Please look at the screen recording below to know what the finished project could look like:
- I used a basic activity to experiment with a floating action button, you can use a standard button.
- I also changed the theme, you can have it your own. Only functionality must be the same.
For this project, we'll be using a top-down coding process. The advantage of doing this is that we can have an app that a user can interact with and then you can add functionality behind it.
- Create a "Book.java" file. Create a class called
Book - This class should have the following data members:
- A
titleString - A
reasonToReadString - A
hasBeenReadboolean - An
idString
- A
- Create two constructors.
a. One that accepts and assigns all data members
b. One that parses a CSV string to an object - Write getters for each of the data members
- Write a
toCsvStringmethod to convert the object to a CSV string
Make sure your CSV constructor and CSV output methods match formatting
- Build your
MainActivitylayout file with aScrollViewand aButton
Make sure the
ScrollViewhas aViewGroupchild with an id for you to add views to
- Write a
buildItemViewmethod which will accept aBookobject and return a custom view to display information about the book.
Typically these views will just show the title of the book. In the next couple weeks, we'll show you how to define custom layouts for lists
- Hardcode a list of
Bookobjects to test your methods. Be sure to add all views returned from yourbuildItemViewmethod to theScrollView's child using.addView(View) - Test your app.
- Add a new empty activity called
EditBookActivity - Add fields to edit information stored in the
Bookobject - Add attributes to the fields to make the layout look good.
- Go into the
AndroidManifextfile and move theintent-filterblock to your new activity. - Build your app and test the new Activity.
- Return the
intent-filterblock to yourMainActivity
Now that you have built both activities. You'll need to link the two activities and pass data between them.
- In your
MainActivityadd anonClickListenerto your button - In the listener create a new
Intentpassing in the currentContextand theEditBookActivity.class - Call
startActivity()with your newIntent - Build and Run your app to test that the button now navigates to the
EditBookActivity
Now that the activity can be launched, it needs data. We have two unique use cases that we'll have to deal with.
A. New Entry
1. Use putExtra to add a new id value to pass to the EditBookActivity
For now, you can use the method
getChildCountto use the item count as a unique id
2. In the onCreate method of the EditBookActivity use getIntent().getStringExtra() to get the passed id
B. Edit Entry
1. In your buildItemView, give the created item an onClickListener
2. This onClickListener must create an Intent just like the button, but this one will add the Book as a CSV string to the Intent
C. Accept Data
Now that we have data in the Intent, we need to get it from the Intent
1. In the onCreate method of your EditBookActivity use getIntent() to get a handle on the Intent
2. Use getExtra and pass it your tag for id to pull the id from the Intent
3. Use getStringExtra to get your Book which was encoded as a CSV string
4. If your Book string isn't null, use it to build a Book object and pull the components from it.
5. Add your data as text to your EditText fields.
Once your EditTextActivity can accept and process data, it needs to return that data back to the MainActivity.
- Write a method called
returnDatawhich will pull the information from all the edit fields, use it to build aBookobject, and convert theBookto a CSV string. - Create a new
Intentand usesetResultwithRESULT_OKto add the CSV string to the intent - Call
finish()to complete the activity and return. - Override the
onBackPressed()method to intercept when the user presses the back button and call yourreturnData - Add two buttons, one as a submit and one as a cancel.
- In the submit button's
onClickListenercall yourreturnDatamethod - For the cancel button write a new method that functions similarly to
returnDatabut doesn't pull data from the UI and usessetResultwithRESULT_CANCELEDinstead - In your
MainActivity, change your calls tostartActivitytostartActivityForResultand pass in a constant tag representing which result you will be looking for. - Override the
onActivityResultmethod to get the returned data - Check first that the result code is
RESULT_OKthen check for the result tag to match the one you passed in - Use
getStringExtrato grab the string from the providedIntent - Parse the CSV string into a
Bookobject - Add the book object to your list of books
Check to see if the id of the book in question already exists, if so, update that entry instead of adding a new one
- Update the UI with the new list
- Test your app
Now that we have a functioning app, we need to add our persistence to it. To do this using SharedPreferences, we'll store our objects as strings by their id. We will also store a list of active objects in a list of ids. Finally, we'll store a single id value representing the next id to be used
- Create a
SharedPreferencesdata member calledpreferencesin yourMainActivity - In the
onCreatemethod of that activity, usethis.getSharedPreferencesto store a handle to the activity'sSharedPreferencesobject in yourpreferencesmember.
This isn't the safest way to access
SharedPreferencesbut it works for a simple app like this. Be sure to check ifpreferencesis null before trying to access it.
- Pass in a
Constant Stringvalue as theSharedPreferencesname andMODE_PRIVATEas its access mode. - Create a class called
SharedPrefsDao, all members of this class will be static - Create constant keys for id list retreival and next id retreival.
- Create methods that use these keys to return
Strings which are retreived fromSharedPreferences. These methods should be namedgetAllBookIdsandgetNextId
These are methods which will simply return the value given when calling
MainActivity.preferences.getString()and passing in the right key
- Create a method that will accept a
Book's id and return theBookCSV string - Create a method to store a book called
updateBookwhich accepts a singleBookobject - This method will check to see if the provided book is new or an updated version of the same book, if it is new, it will add the id to the list of active ids and increment the next id. The method will then store the book using its id as the key.
- Build your app to make sure it compiles properly.
A model, like a repository in MVVM architecture is in charge of managing the data sources and providing a consistent interface to the next layer in the app. In this app, since we only have one data source, it will merely act as a Facade that will parse the string data.
- Create a new class called
BooksModel - Write separate methods that will work with yout
SharedPrefsDaoto return the following a. an array of allBookobjects, accepting no parameters b. a singleBookobject, accepting an id parameter c. the next id to be used, accepting no parameters - Write a method which will pass a
Bookparameter to theupateBookmethod - Build your app to make sure it compiles properly.
- Create a class called
BooksContoller - Refactor your
buildItemViewmethod to move it to your new class.
In order to call
startActivityForResultin this method, you'll need to pass a handle to the activity you'll be building
- Remove your list of
Bookobjects, the loop to build their views, and theLinearLayout. - In your
BookControllerwrite a method calledgetBooksViewthat accepts aContextobject - In the new method, you'll get the list of book objects from the
BooksModel, create a newLinearLayoutobject, usebuildItemViewto add view items to it, and return theLinearLayoutview.
use
imageView.getLayoutParams().width= ViewGroup.LayoutParams.MATCH_PARENT;to set the with to match parent in your list items
- Write a method called
handleEditActivityResultwhich will accept anIntentobject, pull the returned data from it and use it to update the model.
This will replace some of the code in the
onActivityResultmethod of yourMainActivity
- In the
onActivityResultmethod, you will now check the requestCode and the resultCode and call thehandleEditActivityResultmethod, passing it theIntentobject. - In the
onCreatemethod, you will now get a handle to theScrollViewand then call thegetBooksViewand pass that result to theScrollView'saddViewmethod. - Test the app
In your testing, find bugs and small feature improvements that can improve the polish of your app.
