4. Android Architecture Components
Make it easier and more fun to write robust apps, empowering developers to focus
on areas where they can innovate.
Issues like complex lifecycles and the lack of a recommended app architecture
make it challenging to write robust apps.
7. App Architecture Concepts
Abstraction layer over SQLite
● Room - light ORM library
● Allows fluent database access
Repository
● Responsible for handling data
operations.
● Knows where to get the data from and
what API calls to make when data is
updated
8.
9. Room
@Entity
class User {
private @PrimaryKey int uid;
private @ColumnInfo(name = "first_name") String firstName;
}
@Dao
interface UserDao {
@Query("SELECT * FROM user ORDER BY first_name ASC")
public abstract List<User> usersByLastName();
}
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}
11. Room & LiveData
@Entity
class User {
private @PrimaryKey int uid;
private @ColumnInfo(name = "first_name") String firstName;
}
@Dao
interface UserDao {
@Query("SELECT * FROM user ORDER BY first_name ASC")
public abstract LiveData<List<User>> usersByLastName();
}
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}
12. App Architecture Concepts
ViewModel
● Stores UI-related data in a lifecycle
conscious way
Lifecycle-aware components
● LifecycleOwner / LifecycleObserver
13. Room & LiveData & ViewModel
@Entity
class User {
private @PrimaryKey int uid;
private @ColumnInfo(name = "first_name") String firstName;
}
@Dao
interface UserDao {
@Query("SELECT * FROM user ORDER BY first_name ASC")
public abstract LiveData<List<User>> usersByLastName();
}
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}
class MyViewModel extends ViewModel {
public final LiveData<List<User>> usersList;
public MyViewModel() {
AppDatabase db = Room.databaseBuilder(context,
AppDatabase.class, "database-name").build();
usersList = db.userDao().usersByLastName();
}
}
14. Room & LiveData & ViewModel & UI
@Entity
class User {
private @PrimaryKey int uid;
private @ColumnInfo(name = "first_name") String firstName;
}
@Dao
interface UserDao {
@Query("SELECT * FROM user ORDER BY first_name ASC")
public abstract LiveData<List<User>> usersByLastName();
}
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}
class MyViewModel extends ViewModel {
public final LiveData<List<User>> usersList;
public MyViewModel() {
AppDatabase db = Room.databaseBuilder(context,
AppDatabase.class, "database-name").build();
usersList = db.userDao().usersByLastName();
}
}
class MyActivity extends AppCompatActivity {
@Override
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
MyViewModel viewModel = ViewModelProviders.of(this)
.get(MyViewModel.class);
// ...
}
}
15. Data Flow
Room
Use Room to store the new data
in the SQLite database for
offline use
ViewModel
Store the data in a ViewModel
object to make it accessible for
UI objects
BE Service
Use the Retrofit library to
access your backend and fetch
for data
LiveData
Use Room to fetch data from
the SQLite database and get
LiveData objects
UI
Activities access the data using
the ViewModel. They observe
and respond to changes
18. Why paging is interesting
● We use SQLiteCursor for fetching data from the database
● SQLiteCursor uses a CursorWindow, a buffer of rows typically 2MB in size
● Challenges:
○ SQLiteCursor doesn’t hold any database transaction open
○ SQLiteCursor.getCount() scans entire query
○ SQLiteCursor does not know data has changed
24. Room & LiveData & ViewModel & UI & Paging
@Entity
class User {
private @PrimaryKey int uid;
private @ColumnInfo(name = "first_name") String firstName;
}
@Dao
interface UserDao {
@Query("SELECT * FROM user ORDER BY first_name ASC")
public abstract LiveData<List<User>> usersByLastName();
}
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}
25. Room & LiveData & ViewModel & UI & Paging
@Entity
class User {
private @PrimaryKey int uid;
private @ColumnInfo(name = "first_name") String firstName;
}
@Dao
interface UserDao {
@Query("SELECT * FROM user ORDER BY first_name ASC")
public abstract DataSource.Factory<Integer, User> usersByLastName();
}
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}
26. Room & LiveData & ViewModel & UI & Paging
@Entity
class User {
private @PrimaryKey int uid;
private @ColumnInfo(name = "first_name") String firstName;
}
@Dao
interface UserDao {
@Query("SELECT * FROM user ORDER BY first_name ASC")
public abstract DataSource.Factory<Integer, User> usersByLastName();
}
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}
class MyViewModel extends ViewModel {
LiveData<List<User>> usersList;
public MyViewModel() {
AppDatabase db = Room.databaseBuilder(context,
AppDatabase.class, "database-name").build();
usersList = db.userDao().usersByLastName();
}
}
27. Room & LiveData & ViewModel & UI & Paging
@Entity
class User {
private @PrimaryKey int uid;
private @ColumnInfo(name = "first_name") String firstName;
}
@Dao
interface UserDao {
@Query("SELECT * FROM user ORDER BY first_name ASC")
public abstract DataSource.Factory<Integer, User> usersByLastName();
}
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}
class MyViewModel extends ViewModel {
LiveData<PagedList<User>> usersList;
public MyViewModel() {
AppDatabase db = Room.databaseBuilder(context,
AppDatabase.class, "database-name").build();
usersList = new LivePagedListBuilder<>(
db.userDao.usersByLastName(),20).build();
}
}
28. Room & LiveData & ViewModel & UI & Paging
@Entity
class User {
private @PrimaryKey int uid;
private @ColumnInfo(name = "first_name") String firstName;
}
@Dao
interface UserDao {
@Query("SELECT * FROM user ORDER BY first_name ASC")
public abstract DataSource.Factory<Integer, User> usersByLastName();
}
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}
class MyViewModel extends ViewModel {
LiveData<PagedList<User>> usersList;
public MyViewModel() {
AppDatabase db = Room.databaseBuilder(context,
AppDatabase.class, "database-name").build();
usersList = new LivePagedListBuilder<>(
db.userDao.usersByLastName(),20).build();
}
}
class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
MyViewModel viewModel = ViewModelProviders.of(this).
get(MyViewModel.class);
viewModel.usersList.observe(this, new Observer<PagedList<User>>() {
void onChanged(PagedList<User> users) {
adapter.setList(users);
}
});
}