Persistence in Android 4.x

Uploaded on

How to deal with persistence when writing Android 4.x applications …

How to deal with persistence when writing Android 4.x applications

The source code is available at

More in: Education
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads


Total Views
On Slideshare
From Embeds
Number of Embeds



Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

    No notes for slide


  • 1. Persistence Ilio Catallo, Eleonora Ciceri – Politecnico di Milano,
  • 2. TakeNotes current state ¤  TakeNotes is able to add and delete to-do items ¤  However, when the application is closed, the list is deleted, since items are not stored in persistent state ¤  Solution: use a database to store items ¤  Each time a to-do item is added to the list, it is stored in the database too ¤  When the application is launched, the list is loaded from the database 2
  • 3. Persistence in Android 3
  • 4. Android storage options ¤  Android provides several ways to store users and application data: ¤  Shared Preferences ¤  Internal / External Storage ¤  Network Connections ¤  SQLite Databases ¤  Databases are particularly suited when storing large amounts of the same structured data 4
  • 5. Example: TakeNotes # to-do item Text 1! Send an e-mail to T.A.’s! 2! Deliver project specifications! 3! Buy milk! 5 ¤  In TakeNotes, we need at least to store the text of each to-do item in the list
  • 6. Introducing SQLite ¤  SQLite is a SQL database engine ¤  It is implemented as a C library ¤  SQLite’s main features: ¤  Open-source ¤  Standard-compliant ¤  Lightweight ¤  Single-tier ¤  SQLite is natively supported in Android, and it provides a a robust persistence layer over which you have total control 6
  • 7. Setting up a database ¤  No database is automatically provided with the application, If you want to use SQLite, you have to: ¤  Create your own database ¤  Create tables ¤  Populate it with data ¤  Any databases will be accessible by name to any class in the application, but not outside the application 7
  • 8. Persistence layer 8
  • 9. Business logic layer vs. persistence layer (1) ¤  You do not want the business logic code to deal directly with the problem of persisting data 9 Activity 3 Data source Activity 1 Activity 2 SQL statements are scattered everywhere in the codebase If you change the relational model you have to change the code everywhere
  • 10. Business logic layer vs. persistence layer (2) ¤  It would be better have a central authority responsible for persisting the data ¤  The business logic can interact with such a central authority, without caring of how the data are actually persisted 10 Central authority (repository) Data source Activity 1 Activity 2 Activity 3 Businesslayer
  • 11. The Repository pattern ¤  Since the central authority is usually referred to as the repository, the resulting design pattern is called the Repository pattern ¤  The repository act as a mediator between the business logic layer and the data source layer ¤  The repository is usually implemented as a helper class whose methods will be invoked by the business layer code 11
  • 12. The SQLite repository class (1) ¤  The recommended method to create a new SQLite database is to create a subclass of SQLiteOpenHelper! ¤  SQLiteOpenHelper is the repository class that manages interactions with the database ¤  The subclass of SQLiteOpenHelper will: ¤  Take care of opening the database if it exists ¤  Create the database if it does not exist ¤  Upgrade the database if it is necessary 12
  • 13. The SQLite repository class (2) ¤  DatabaseHandler is the repository class for our application ¤  It is obtained by extending the SQLiteOpenHelper class provided by Android 13
  • 14. Creating a database 14
  • 15. Anatomy of a SQLite database ¤  SQLite databases are stored in the /data/data/package_name/databases folder on your device or emulator ¤  Each SQLite database is characterized by the following properties: ¤  A human-readable name ¤  A version number 15
  • 16. Creating databases ¤  If not already present, the database is created on disk the first time the application tries to access the data ¤  The database is upgraded every time a mismatch between version numbers is detected. ¤  Typical use case: ¤  As a new app update requires a change in the database schema, the version number is increased ¤  The app detects the mismatch and upgrades the schema of the locally stored database 16
  • 17. Creatingdatabases 17 Application starts DB exists? Create the DB on disk No Yes Is version number the same? Yes Upgrade the DB on disk No First access
  • 18. Creating a database (2) ¤  The create/upgrade lifecycle is implemented in the repository class by means of three methods: ¤  The constructor ¤  The onCreate() method ¤  the onUpdate() method 18
  • 19. Creatingdatabases 19 Application starts DB exists? onCreate()! No Yes Is version number the same? Yes onUpgrade()! No First access DatabaseHandler()!
  • 20. Overriding the constructor (1) ¤  The repository class’ constructor informs the system that the application wants to create a database ¤  Together with other parameters, it specifies: ¤  The name of the database ¤  The current version number 20
  • 21. Overriding the constructor (2) 21 Constants are usually stored as static data members The Context object is needed to actually create the database (see reference) An optional CursorFactory, typically just pass null!
  • 22. Overriding the onCreate()
 method (1) ¤  The onCreate() method is called when the database is created for the first time ¤  The method is responsible for the creation of tables ¤  Remember: the method will not be called if no operation is performed on the database 22
  • 23. Overriding the onCreate()
 method (2) 23 a new table named todo is createdthe execSQL() method works for any SQL that does not return a result
  • 24. Overriding the onUpgrade()
 method (1) ¤  The onUpgrade() method upgrades the existing database to conform to the new version ¤  This method should drop tables, add tables, or do anything else it needs to upgrade to the new schema version ¤  Remember: the method will not be called if no operation is performed on the database 24
  • 25. Overriding the onUpgrade()
 method (2) 25 Snippet taken from: The database is upgraded from oldVersion to newVersion by cascading upgrade statement
  • 26. Overriding the onUpgrade()
 method (3) ¤  The simplest upgrading policy is to drop the old table and create a new one 26 The todo table is droppedThe todo table is created from scratch
  • 27. Obtaining the database ¤  To access a database using the repository class, call: ¤  getReadableDatabase() to obtain a read-only instance of the database ¤  getWritableDatabase() to obtain a read-write instance of the database ¤  After invoking one of the two methods: ¤  If the DB does not exist, onCreate() will be called ¤  If the DB needs to be upgraded, onUpgrade() will be called 27
  • 28. Creatingdatabases 28 Application starts DB exists?onCreate()! No Yes Is version number the same? Yes onUpgrade()! No First access DatabaseHandler()! getWritableDatabase()!
  • 29. Interacting with the database 29
  • 30. Object model vs. Relational model (1) ¤  The data you want to persist are usually encoded as class instances, i.e., as objects ¤  Example: starting from TakeNotes v4, the to-do items are modeled as instances of a ToDo class 30
  • 31. Object model vs. Relational model (2) ¤  On the other hand, relation databases organize information as tuples and rows ¤  Example: the database for TakeNotes v4 can be made of just one table named todo! 31 # to-do item Text 1! Send an e-mail to T.A.’s! 2! Deliver project specifications! 3! Buy milk!
  • 32. Object-Relational Mapping (1) ¤  As such: ¤  The business logic code deals with class instances ¤  The database deals with tables and rows ¤  We need a mediator to manage the automatic transformation of objects to tuples and vice versa ¤  The technique of mapping objects to tuples (and vice versa) is known as object-relational mapping (ORM) 32
  • 33. Object-Relational Mapping (2) ¤  A possible solution is to make the repository responsible of providing a object-relation mapping (ORM) mechanism 33 Central authority (repository) Data source Activity 1 Activity 2 Activity 3 Businesslayer Java objects Tables and rows
  • 34. Object-Relational Mapping (3) ¤  The issue of mapping objects to tuples is a non-trivial one ¤  Developers spend effort in writing lots of code to convert row and column data into objects ¤  Android put the entire burden on the developers ¤  It is up to the developer to correctly performe the mapping ¤  Third-party libraries are available 34
  • 35. Writing data into the database ¤  The repository class should expose methods to persist objects into the database ¤  Example: In TakeNotes, business logic code can persist a ToDo class instances by invoking the addToDo method on the repository class instance 35
  • 36. Transforming objects into tuples (1) ¤  The repository class needs to convert objects into tuples ¤  Android represents tuples as ContentValues class instances 36 not needed if the id column is auto-incremented
  • 37. Transforming objects into tuples (1) ¤  Once a tuple has been populated, it is ready to be inserted into the database 37 Object-relational mapping
  • 38. The NULL value hack ¤  While permitted in SQL, SQLite forbids to insert an empty tuple, i.e., an empty ContentValues object ¤  If you pass an empty ContentValues to insert(), you must also provide the name of a column that SQLite will explicitly set to NULL! 38 Name of the column that will be set to NULL just pass null if you know that the ContentValues is not empty
  • 39. Querying the database ¤  There exist two ways of querying the database: ¤  Use rawQuery() to execute a SQL statement directly ¤  use query() to build up a query from its component parts 39
  • 40. Querying with rawQuery()! ¤  The most immediate approach for querying the database is to use rawQuery()! 40 In case of parametric queries, parameter values must be specified here
  • 41. Querying with query() (1) ! ¤  The query() method takes the discrete pieces of a SELECT statement and builds the query from them. ¤  The pieces are: ¤  the name of the table to query against ¤  The list of columns to retrieve ¤  The WHERE clause (with possible positional parameters) ¤  The positional parameter values ¤  The GROUP BY clause, if any ¤  The HAVING clause, if any ¤  The ORDER BY clause, if any 41
  • 42. Querying with query() (2) 42 SELECT * ! FROM todo ! WHERE id=1 OR id=2! ORDER BY clause HAVING clause GROUP BY clause equivalent to SELECT *
  • 43. The result set ¤  A query result set are returned as a Cursor object ¤  A Cursor contains method for iterating over results ¤  With a Cursor you can: ¤  Find how many rows are in the result set via getCount()! ¤  Iterate over the tuples via moveToFirst(), moveToNext() and isAfterLast()! ¤  Re-execute the query that created the cursor via requery()! ¤  Release the cursor’s resources via close()! 43
  • 44. Result sets as lists of objects (1) ¤  The repository class is responsible for transforming tuples in the result set into a list of objects ¤  The repository class exposes methods that return collection of objects 44
  • 45. Result sets as lists of objects (2) 45 Object-relational mapping
  • 46. References 46
  • 47. References ¤  Reto Meier, Professional Android 4 Application development 3rd Ed., Wrox! ¤  SQLiteOpenHelper class reference: database/sqlite/SQLiteOpenHelper.html ¤  SQLiteDatabase class reference: database/sqlite/SQLiteDatabase.html 47
  • 48. References ¤  Android API Guides, Storage Options storage.html ¤  Android SQLite Database Tutorial: tutorial/ ¤  MSDN, the Repository pattern ¤  Martin Fowler, The Repository pattern 48