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
title
String - A
reasonToRead
String - A
hasBeenRead
boolean - An
id
String
- 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
toCsvString
method to convert the object to a CSV string
Make sure your CSV constructor and CSV output methods match formatting
- Build your
MainActivity
layout file with aScrollView
and aButton
Make sure the
ScrollView
has aViewGroup
child with an id for you to add views to
- Write a
buildItemView
method which will accept aBook
object 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
Book
objects to test your methods. Be sure to add all views returned from yourbuildItemView
method 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
Book
object - Add attributes to the fields to make the layout look good.
- Go into the
AndroidManifext
file and move theintent-filter
block to your new activity. - Build your app and test the new Activity.
- Return the
intent-filter
block to yourMainActivity
Now that you have built both activities. You'll need to link the two activities and pass data between them.
- In your
MainActivity
add anonClickListener
to your button - In the listener create a new
Intent
passing in the currentContext
and 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
getChildCount
to 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
returnData
which will pull the information from all the edit fields, use it to build aBook
object, and convert theBook
to a CSV string. - Create a new
Intent
and usesetResult
withRESULT_OK
to 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
onClickListener
call yourreturnData
method - For the cancel button write a new method that functions similarly to
returnData
but doesn't pull data from the UI and usessetResult
withRESULT_CANCELED
instead - In your
MainActivity
, change your calls tostartActivity
tostartActivityForResult
and pass in a constant tag representing which result you will be looking for. - Override the
onActivityResult
method to get the returned data - Check first that the result code is
RESULT_OK
then check for the result tag to match the one you passed in - Use
getStringExtra
to grab the string from the providedIntent
- Parse the CSV string into a
Book
object - 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
SharedPreferences
data member calledpreferences
in yourMainActivity
- In the
onCreate
method of that activity, usethis.getSharedPreferences
to store a handle to the activity'sSharedPreferences
object in yourpreferences
member.
This isn't the safest way to access
SharedPreferences
but it works for a simple app like this. Be sure to check ifpreferences
is null before trying to access it.
- Pass in a
Constant String
value as theSharedPreferences
name andMODE_PRIVATE
as 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
String
s which are retreived fromSharedPreferences
. These methods should be namedgetAllBookIds
andgetNextId
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 theBook
CSV string - Create a method to store a book called
updateBook
which accepts a singleBook
object - 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
SharedPrefsDao
to return the following a. an array of allBook
objects, accepting no parameters b. a singleBook
object, accepting an id parameter c. the next id to be used, accepting no parameters - Write a method which will pass a
Book
parameter to theupateBook
method - Build your app to make sure it compiles properly.
- Create a class called
BooksContoller
- Refactor your
buildItemView
method to move it to your new class.
In order to call
startActivityForResult
in this method, you'll need to pass a handle to the activity you'll be building
- Remove your list of
Book
objects, the loop to build their views, and theLinearLayout
. - In your
BookController
write a method calledgetBooksView
that accepts aContext
object - In the new method, you'll get the list of book objects from the
BooksModel
, create a newLinearLayout
object, usebuildItemView
to add view items to it, and return theLinearLayout
view.
use
imageView.getLayoutParams().width= ViewGroup.LayoutParams.MATCH_PARENT;
to set the with to match parent in your list items
- Write a method called
handleEditActivityResult
which will accept anIntent
object, pull the returned data from it and use it to update the model.
This will replace some of the code in the
onActivityResult
method of yourMainActivity
- In the
onActivityResult
method, you will now check the requestCode and the resultCode and call thehandleEditActivityResult
method, passing it theIntent
object. - In the
onCreate
method, you will now get a handle to theScrollView
and then call thegetBooksView
and pass that result to theScrollView
'saddView
method. - Test the app
In your testing, find bugs and small feature improvements that can improve the polish of your app.