Lecture3-HTTP API calls - UI component navigation - sqlite persistence
Lecture3-HTTP API calls - UI component navigation - sqlite persistence
h t t p s: / / sq u ar e. g i t h u b . i o / r et r o f i t /
REST using Retrofit
implementation "com.squareup.retrofit2:retrofit:version"
implementation "com.squareup.retrofit2:adapter-rxjava2:version"
implementation "com.squareup.retrofit2:converter-gson:version"
implementation “io.reactivex.rxjava2:rxandroid:version"
h t t p s: / / sq u ar e. g i t h u b . i o / r et r o f i t /
interface MovieService {
REST using Retrofit
@GET("movies")
val movies: Observable<List<Movie>>
@POST("update")
@GET("genres") fun update(@Body movie: Movie): Observable<Movie>
val genres: Observable<List<String>>
@DELETE("delete/{id}")
@GET("moviesByGenre/{genre}") fun delete(@Path("id") id: Int): Observable<ResponseBody>
fun moviesByGenre(@Path("genre") genre: String)
: Observable<List<Movie>> @POST("add")
fun add(@Body movie: Movie): Observable<Movie>
@GET("details/{id}")
fun details(@Path("id") id: Int): Observable<Movie> companion object {
const val SERVICE_ENDPOINT = “http://SERVER_IP:2022”
@POST("updateDescription") }
fun updateDescription(@Body movie: Movie): Observable<Movie> }
@POST("updateRating")
fun updateRating(@Body movie: Movie): Observable<Movie>
h t t p s: / / sq u ar e. g i t h u b . i o / r et r o f i t /
Navigation
Key concepts
h t t p s : / / d e ve l o p e r. a n d r o i d . c o m / g u i d e / n a vi g a t i o n
Navigation
Navigation Components:
• A collection of libraries
• A plugin
• Tooling
Navigation
• Navigation Graph
• NavHostFragment
• NavController
Navigation
h t t p s : / / d e ve l o p e r. a n d r o i d . c o m / g u i d e / n a vi g a t i o n
Navigation Drawer
• Appears:
h t t p s: / / d e ve l o p e r. an d r o i d . c o m / t r a i n i n g / i m p l e m en t i n g - n a v i g a t i o n / n a v - d r a w e r
Create a navigation drawer views
activity project
Generated Artifacts (xml)
• Sources
• Layouts
• Menus
• Navigation
Dependencies
buildscript {
ext.nav_version = “2.5.3”
}
…
dependencies {
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
}
Add a drawer to a layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="@layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.navigation.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header_main"
app:menu="@menu/activity_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>
Declare the menu items
<android.support.design.widget.NavigationView
android:id=“@+id/nav_view”
android:layout_width=“wrap_content”
android:layout_height=“match_parent”
android:layout_grvity=“start”
android:IfitsSystemWindows=“true”
app:menu=“@menu/activity_main_drawer” />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="My header title"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>
</LinearLayout>
Handle navigation events
class MainActivity : AppCompatActivity() {
appBarConfiguration = AppBarConfiguration(
setOf(
R.id.nav_home,
R.id.nav_gallery
), drawer_layout
)
setupActionBarWithNavController(navController, appBarConfiguration)
nav_view.setupWithNavController(navController)
}
}
Local Persistence Options
• Internal storage
• External storage
• Shared preferences
• Databases
h t t p s : / / d e ve l o p e r. a n d r o i d . c o m / g u i d e / t o p i c s / d a t a /
Options
•On device:
•SQLite
•Realm
•Room
•SQLDelight
•ObjectBox
•On cloud:
•Firebase Realtime Database
•Firebase Firestore
•Couchbase Lite
SQLite
Define a schema and a contract
object FeedReaderContract {
// Table contents are grouped
// together in an anonymous object.
object FeedEntry : BaseColumns {
const val TABLE_NAME = "entry"
const val COLUMN_NAME_TITLE = "title"
const val COLUMN_NAME_SUBTITLE = "subtitle"
}
}
h t t p s : / / d e ve l o p e r. a n d r o i d . c o m / t r a i n i n g / d a t a - s t o r a g e / s q l i t e
SQLite Helper
Create a database using an SQL helper
companion object {
// If you change the database schema, you must increment the database version.
const val DATABASE_VERSION = 1
const val DATABASE_NAME = "FeedReader.db"
}
}
SQLite - Insert
// Gets the data repository in write mode
val db = dbHelper.writableDatabase
// Create a new map of values, where column names are the keys
val values = ContentValues().apply {
put(FeedEntry.COLUMN_NAME_SUBTITLE, subtitle)
}
// Insert the new row, returning the primary key value of the new row
val newRowId = db?.insert(FeedEntry.TABLE_NAME, null, values)
SQLite - Query
val dbHelper = FeedReaderDbHelper(context)
val db = dbHelper.readableDatabase
// Define a projection that specifies which columns from the database
// you will actually use after this query.
val projection = arrayOf(
BaseColumns._ID,
FeedEntry.COLUMN_NAME_TITLE,
FeedEntry.COLUMN_NAME_SUBTITLE)
// Filter results WHERE "title" = 'My Title'
val selection = "${FeedEntry.COLUMN_NAME_TITLE} = ?"
val selectionArgs = arrayOf("My Title")
// How you want the results sorted in the resulting Cursor
val sortOrder = "${FeedEntry.COLUMN_NAME_SUBTITLE} DESC"
val cursor = db.query(
SQLite - Query
val dbHelper = FeedReaderDbHelper(context)
val db = dbHelper.readableDatabase
val projection = arrayOf(...)
val selection = "${FeedEntry.COLUMN_NAME_TITLE} = ?"
val selectionArgs = arrayOf("My Title")
val sortOrder = "${FeedEntry.COLUMN_NAME_SUBTITLE} DESC"
val cursor = db.query(...)
val itemIds = mutableListOf<Long>()
with(cursor) {
while (moveToNext()) {
val itemId = getLong(getColumnIndexOrThrow(BaseColumns._ID))
itemIds.add(itemId)
}
}
SQLite - Delete
val dbHelper = FeedReaderDbHelper(context)
val db = dbHelper.writableDatabase
// Define 'where' part of query.
val selection = "${FeedEntry.COLUMN_NAME_TITLE} LIKE ?"
// Specify arguments in placeholder order.
val selectionArgs = arrayOf("MyTitle")
// Issue SQL statement.
val deletedRows = db.delete(FeedEntry.TABLE_NAME, selection, selectionArgs)
SQLite - Update
val dbHelper = FeedReaderDbHelper(context)
val db = dbHelper.writableDatabase
// New value for one column
val title = "MyNewTitle"
val values = ContentValues().apply {
put(FeedEntry.COLUMN_NAME_TITLE, title)
}
// Which row to update, based on the title
val selection = "${FeedEntry.COLUMN_NAME_TITLE} LIKE ?"
val selectionArgs = arrayOf("MyOldTitle")
val count = db.update(
FeedEntry.TABLE_NAME,
values,
)