Major updates to drawer header layout. Added extension methods for doubles in shared preferences. Code cleanup.

This commit is contained in:
Arty Bishop committed 2019-10-26 21:35:45 +01:00
1 parent f24edc62a0
commit 2b41402e5c
15 files changed
+155 -162

No files matched your search

-1
View File
@@ -47,7 +47,6 @@ dependencies {
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle" implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle"
implementation "androidx.work:work-runtime-ktx:$work" implementation "androidx.work:work-runtime-ktx:$work"
implementation "androidx.paging:paging-runtime:$paging"
implementation "androidx.room:room-runtime:$room" implementation "androidx.room:room-runtime:$room"
implementation "androidx.room:room-ktx:$room" implementation "androidx.room:room-ktx:$room"
kapt "androidx.room:room-compiler:$room" kapt "androidx.room:room-compiler:$room"
@@ -12,6 +12,7 @@ import android.os.CountDownTimer
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
@@ -49,7 +50,9 @@ class MainActivity : AppCompatActivity() {
private lateinit var preferences: SharedPreferences private lateinit var preferences: SharedPreferences
private lateinit var drawerLat: TextView private lateinit var drawerLat: TextView
private lateinit var drawerLon: TextView private lateinit var drawerLon: TextView
private lateinit var drawerHeight: TextView
private lateinit var drawerSubTitle: TextView private lateinit var drawerSubTitle: TextView
private lateinit var drawerGetLocation: ImageView
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@@ -57,12 +60,7 @@ class MainActivity : AppCompatActivity() {
setupComponents() setupComponents()
setupNavigation() setupNavigation()
setupTimer() setupTimer()
updateDrawerText() updateDrawerValues()
}
private fun updateDrawerText() {
drawerLat.text = preferences.getString("LATITUDE", "-180.0000")?.substring(0, 9)
drawerLon.text = preferences.getString("LONGITUDE", "-60.0000")?.substring(0, 9)
} }
private fun setupComponents() { private fun setupComponents() {
@@ -82,7 +80,9 @@ class MainActivity : AppCompatActivity() {
val header = navView.getHeaderView(0) val header = navView.getHeaderView(0)
drawerLat = header.findViewById(R.id.drawer_lat_value) drawerLat = header.findViewById(R.id.drawer_lat_value)
drawerLon = header.findViewById(R.id.drawer_lon_value) drawerLon = header.findViewById(R.id.drawer_lon_value)
drawerSubTitle = header.findViewById(R.id.drawer_subtitle) drawerHeight = header.findViewById(R.id.drawer_height_value)
drawerSubTitle = header.findViewById(R.id.drawer_link)
drawerGetLocation = header.findViewById(R.id.drawer_get_location)
val navController = findNavController(R.id.nav_host) val navController = findNavController(R.id.nav_host)
appBarConfig = AppBarConfiguration(setOf(R.id.nav_sky), drawerLayout) appBarConfig = AppBarConfiguration(setOf(R.id.nav_sky), drawerLayout)
@@ -109,6 +109,10 @@ class MainActivity : AppCompatActivity() {
drawerSubTitle.setOnClickListener { drawerSubTitle.setOnClickListener {
openGitHub() openGitHub()
} }
drawerGetLocation.setOnClickListener {
updateLocation()
}
} }
private fun setupTimer() { private fun setupTimer() {
@@ -138,27 +142,6 @@ class MainActivity : AppCompatActivity() {
} }
private fun updateLocation() { private fun updateLocation() {
fusedLocationClient.lastLocation.addOnSuccessListener { location: Location? ->
val currentLat = location?.latitude
val currentLon = location?.longitude
val currentHeight = location?.altitude
preferences.edit {
putString("LATITUDE", currentLat.toString())
putString("LONGITUDE", currentLon.toString())
putString("HEIGHT", currentHeight.toString())
apply()
}
updateDrawerText()
}
}
private fun openGitHub() {
val intentGitHub = Intent(Intent.ACTION_VIEW, Uri.parse(GITHUB_URL))
startActivity(intentGitHub)
}
private fun checkPermissions() {
if (ContextCompat.checkSelfPermission(this, LOCATION_PERM) != GRANTED) { if (ContextCompat.checkSelfPermission(this, LOCATION_PERM) != GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, LOCATION_PERM)) { if (ActivityCompat.shouldShowRequestPermissionRationale(this, LOCATION_PERM)) {
Toast.makeText(this, "Missing permissions", Toast.LENGTH_LONG).show() Toast.makeText(this, "Missing permissions", Toast.LENGTH_LONG).show()
@@ -166,10 +149,41 @@ class MainActivity : AppCompatActivity() {
ActivityCompat.requestPermissions(this, arrayOf(LOCATION_PERM), LOCATION_REQ) ActivityCompat.requestPermissions(this, arrayOf(LOCATION_PERM), LOCATION_REQ)
} }
} else { } else {
updateLocation() getPreciseLocation()
} }
} }
private fun getPreciseLocation() {
fusedLocationClient.lastLocation.addOnSuccessListener { location: Location? ->
val lat = location?.latitude ?: 0.0
val lon = location?.longitude ?: 0.0
val height = location?.altitude ?: 0.0
preferences.edit {
putDouble("LATITUDE", lat)
putDouble("LONGITUDE", lon)
putDouble("HEIGHT", height)
apply()
}
updateDrawerValues()
}
}
private fun updateDrawerValues() {
val lat = preferences.getDouble("LATITUDE", 0.0)
val lon = preferences.getDouble("LONGITUDE", 0.0)
val height = preferences.getDouble("HEIGHT", 0.0)
drawerLat.text = String.format("%.4f", lat)
drawerLon.text = String.format("%.4f", lon)
drawerHeight.text = String.format("%.1fm", height)
}
private fun openGitHub() {
val intentGitHub = Intent(Intent.ACTION_VIEW, Uri.parse(GITHUB_URL))
startActivity(intentGitHub)
}
override fun onRequestPermissionsResult( override fun onRequestPermissionsResult(
requestCode: Int, requestCode: Int,
permissions: Array<out String>, permissions: Array<out String>,
@@ -178,7 +192,7 @@ class MainActivity : AppCompatActivity() {
when (requestCode) { when (requestCode) {
LOCATION_REQ -> { LOCATION_REQ -> {
if (grantResults.isNotEmpty() && grantResults[0] == GRANTED) { if (grantResults.isNotEmpty() && grantResults[0] == GRANTED) {
updateLocation() getPreciseLocation()
} }
} }
} }
@@ -196,7 +210,6 @@ class MainActivity : AppCompatActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) { when (item.itemId) {
R.id.update_location -> checkPermissions()
R.id.fetch_trans -> Toast.makeText(this, "Fetch transmit", Toast.LENGTH_SHORT).show() R.id.fetch_trans -> Toast.makeText(this, "Fetch transmit", Toast.LENGTH_SHORT).show()
R.id.save_to_db -> Toast.makeText(this, "Saving to DB", Toast.LENGTH_SHORT).show() R.id.save_to_db -> Toast.makeText(this, "Saving to DB", Toast.LENGTH_SHORT).show()
R.id.load_from_db -> Toast.makeText(this, "Loading from DB", Toast.LENGTH_SHORT).show() R.id.load_from_db -> Toast.makeText(this, "Loading from DB", Toast.LENGTH_SHORT).show()
@@ -207,3 +220,9 @@ class MainActivity : AppCompatActivity() {
return super.onOptionsItemSelected(item) return super.onOptionsItemSelected(item)
} }
} }
fun SharedPreferences.Editor.putDouble(key: String, double: Double): SharedPreferences.Editor =
putLong(key, java.lang.Double.doubleToRawLongBits(double))
fun SharedPreferences.getDouble(key: String, default: Double) =
java.lang.Double.longBitsToDouble(getLong(key, java.lang.Double.doubleToRawLongBits(default)))
@@ -1,11 +0,0 @@
package com.rtbishop.lookingsat.ui
import android.os.Bundle
import androidx.preference.PreferenceFragmentCompat
import com.rtbishop.lookingsat.R
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.preference, rootKey)
}
}
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#C0C0C0"
android:pathData="M12,8c-2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4 -1.79,-4 -4,-4zM20.94,11c-0.46,-4.17 -3.77,-7.48 -7.94,-7.94L13,1h-2v2.06C6.83,3.52 3.52,6.83 3.06,11L1,11v2h2.06c0.46,4.17 3.77,7.48 7.94,7.94L11,23h2v-2.06c4.17,-0.46 7.48,-3.77 7.94,-7.94L23,13v-2h-2.06zM12,19c-3.87,0 -7,-3.13 -7,-7s3.13,-7 7,-7 7,3.13 7,7 -3.13,7 -7,7z" />
</vector>
+2 -4
View File
@@ -8,15 +8,13 @@
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
android:theme="@style/AppTheme.AppBarOverlay">
<androidx.appcompat.widget.Toolbar <androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary" android:background="?attr/colorPrimary">
app:popupTheme="@style/AppTheme.PopupOverlay">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/timer_layout" android:id="@+id/timer_layout"
+62 -59
View File
@@ -8,92 +8,95 @@
android:theme="@style/ThemeOverlay.AppCompat.Dark"> android:theme="@style/ThemeOverlay.AppCompat.Dark">
<ImageView <ImageView
android:id="@+id/drawer_img" android:id="@+id/drawer_sat_img"
android:layout_width="108dp" android:layout_width="116dp"
android:layout_height="108dp" android:layout_height="116dp"
android:layout_marginStart="16dp"
android:layout_marginTop="32dp" android:layout_marginTop="32dp"
android:layout_marginEnd="16dp"
android:contentDescription="@string/app_name" android:contentDescription="@string/app_name"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_sat_desc_right" /> app:srcCompat="@drawable/ic_sat_desc_left" />
<TextView <TextView
android:id="@+id/drawer_title" android:id="@+id/drawer_title"
android:layout_width="0dp" style="@style/DrawerHeader.Title"
android:layout_height="wrap_content" android:layout_marginStart="8dp"
android:layout_marginTop="16dp" android:text="@string/title"
android:text="@string/drawer_header_title" app:layout_constraintStart_toStartOf="parent"
android:textAppearance="@style/TextAppearance.AppCompat.Title" app:layout_constraintTop_toTopOf="@+id/drawer_sat_img" />
android:textColor="@color/colorDrawerText"
android:textSize="24sp"
app:layout_constraintStart_toStartOf="@+id/drawer_subtitle"
app:layout_constraintTop_toBottomOf="@+id/drawer_img" />
<TextView <TextView
android:id="@+id/drawer_subtitle" android:id="@+id/drawer_subtitle"
android:layout_width="wrap_content" style="@style/DrawerHeader.Title"
android:layout_height="wrap_content" android:text="@string/subtitle"
android:layout_marginStart="16dp" app:layout_constraintStart_toStartOf="@+id/drawer_title"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:text="@string/drawer_header_subtitle"
android:textColor="@color/colorDrawerText"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/drawer_title" /> app:layout_constraintTop_toBottomOf="@+id/drawer_title" />
<TextView <TextView
android:id="@+id/drawer_lat" android:id="@+id/drawer_lat"
android:layout_width="wrap_content" style="@style/DrawerHeader.Item"
android:layout_height="wrap_content"
android:text="@string/latitude" android:text="@string/latitude"
android:textAppearance="@style/TextAppearance.AppCompat.Large" app:layout_constraintBottom_toTopOf="@+id/drawer_lon_value"
android:textColor="@color/colorDrawerText" app:layout_constraintStart_toStartOf="@+id/drawer_lon" />
android:textSize="18sp"
app:layout_constraintBottom_toTopOf="@+id/drawer_lat_value"
app:layout_constraintStart_toStartOf="@+id/drawer_lat_value"
app:layout_constraintTop_toTopOf="@+id/drawer_img" />
<TextView <TextView
android:id="@+id/drawer_lat_value" android:id="@+id/drawer_lat_value"
android:layout_width="wrap_content" style="@style/DrawerHeader.Value"
android:layout_height="wrap_content" android:layout_marginStart="8dp"
android:text="@string/latitude_def" android:text="@string/latitude_def"
android:textAppearance="@style/TextAppearance.AppCompat.Title" app:layout_constraintBaseline_toBaselineOf="@+id/drawer_lat"
android:textColor="@color/colorDrawerText" app:layout_constraintStart_toEndOf="@+id/drawer_lat" />
android:textSize="26sp"
app:layout_constraintBottom_toTopOf="@+id/drawer_lon"
app:layout_constraintStart_toStartOf="@+id/drawer_lon"
app:layout_constraintTop_toBottomOf="@+id/drawer_lat" />
<TextView <TextView
android:id="@+id/drawer_lon" android:id="@+id/drawer_lon"
android:layout_width="wrap_content" style="@style/DrawerHeader.Item"
android:layout_height="wrap_content"
android:text="@string/longitude" android:text="@string/longitude"
android:textAppearance="@style/TextAppearance.AppCompat.Large" app:layout_constraintBottom_toTopOf="@+id/drawer_height_value"
android:textColor="@color/colorDrawerText" app:layout_constraintStart_toStartOf="@+id/drawer_height" />
android:textSize="18sp"
app:layout_constraintBottom_toTopOf="@+id/drawer_lon_value"
app:layout_constraintStart_toStartOf="@+id/drawer_lon_value"
app:layout_constraintTop_toBottomOf="@+id/drawer_lat_value" />
<TextView <TextView
android:id="@+id/drawer_lon_value" android:id="@+id/drawer_lon_value"
android:layout_width="wrap_content" style="@style/DrawerHeader.Value"
android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginEnd="16dp"
android:text="@string/longitude_def" android:text="@string/longitude_def"
android:textAppearance="@style/TextAppearance.AppCompat.Title" app:layout_constraintBaseline_toBaselineOf="@+id/drawer_lon"
android:textColor="@color/colorDrawerText" app:layout_constraintStart_toEndOf="@+id/drawer_lon" />
android:textSize="26sp"
app:layout_constraintBottom_toBottomOf="@+id/drawer_img" <TextView
android:id="@+id/drawer_height"
style="@style/DrawerHeader.Item"
android:layout_marginBottom="8dp"
android:text="@string/height"
app:layout_constraintBottom_toTopOf="@+id/drawer_link"
app:layout_constraintStart_toStartOf="@+id/drawer_link" />
<TextView
android:id="@+id/drawer_height_value"
style="@style/DrawerHeader.Value"
android:layout_marginStart="8dp"
android:text="@string/height_def"
app:layout_constraintBaseline_toBaselineOf="@+id/drawer_height"
app:layout_constraintStart_toEndOf="@+id/drawer_height" />
<ImageView
android:id="@+id/drawer_get_location"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginEnd="32dp"
android:contentDescription="@string/placeholder"
app:layout_constraintBottom_toBottomOf="@+id/drawer_height_value"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/drawer_img" app:layout_constraintTop_toTopOf="@+id/drawer_lat_value"
app:layout_constraintTop_toBottomOf="@+id/drawer_lon" /> app:srcCompat="@drawable/ic_location" />
<TextView
android:id="@+id/drawer_link"
style="@style/DrawerHeader"
android:layout_marginStart="8dp"
android:layout_marginBottom="8dp"
android:text="@string/drawer_header_link"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
-4
View File
@@ -12,10 +12,6 @@
android:title="@string/menu_map" /> android:title="@string/menu_map" />
</group> </group>
<item
android:id="@+id/nav_settings"
android:title="@string/menu_settings" />
<item android:title="@string/menu_about"> <item android:title="@string/menu_about">
<menu> <menu>
<item <item
-4
View File
@@ -1,9 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/update_location"
android:title="@string/menu_update_location" />
<item <item
android:id="@+id/fetch_trans" android:id="@+id/fetch_trans"
android:title="@string/menu_fetch_transmitters" /> android:title="@string/menu_fetch_transmitters" />
@@ -23,11 +23,6 @@
android:label="@string/menu_map" android:label="@string/menu_map"
tools:layout="@layout/fragment_worldmap" /> tools:layout="@layout/fragment_worldmap" />
<fragment
android:id="@+id/nav_settings"
android:name="com.rtbishop.lookingsat.ui.SettingsFragment"
android:label="@string/menu_settings" />
<fragment <fragment
android:id="@+id/nav_credits" android:id="@+id/nav_credits"
android:name="com.rtbishop.lookingsat.ui.CreditsFragment" android:name="com.rtbishop.lookingsat.ui.CreditsFragment"
+1 -1
View File
@@ -5,5 +5,5 @@
<color name="colorAccent">#C0C0C0</color> <color name="colorAccent">#C0C0C0</color>
<color name="colorDrawerText">#C0C0C0</color> <color name="colorDrawerText">#C0C0C0</color>
<color name="colorBackground">#181818</color> <color name="colorBackground">#212121</color>
</resources> </resources>
+1 -1
View File
@@ -1,4 +1,4 @@
<resources> <resources>
<dimen name="drawer_header_height">232dp</dimen> <dimen name="drawer_header_height">280dp</dimen>
<dimen name="fab_margin">16dp</dimen> <dimen name="fab_margin">16dp</dimen>
</resources> </resources>
+10 -8
View File
@@ -1,7 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">LookingSat</string> <string name="app_name">LookingSat</string>
<string name="drawer_header_title">L∞kingSat</string> <string name="title">L∞king</string>
<string name="drawer_header_subtitle">https://github.com/rt-bishop/LookingSat</string> <string name="subtitle">S@t</string>
<string name="drawer_header_link">https://github.com/rt-bishop/LookingSat</string>
<string name="menu_sky">Sky at a Glance</string> <string name="menu_sky">Sky at a Glance</string>
<string name="menu_radar">Radar View</string> <string name="menu_radar">Radar View</string>
@@ -12,14 +14,14 @@
<string name="menu_credits">Credits</string> <string name="menu_credits">Credits</string>
<string name="device_location_summary">Allow the app to get your location</string> <string name="device_location_summary">Allow the app to get your location</string>
<string name="latitude">Latitude:</string> <string name="latitude">Latitude: </string>
<string name="latitude_def">-30.0000</string> <string name="latitude_def">-90.0000</string>
<string name="latitude_summary">Ground station latitude from -90 to 90</string> <string name="latitude_summary">Ground station latitude from -90 to 90</string>
<string name="longitude">Longitude:</string> <string name="longitude">Longitude: </string>
<string name="longitude_def">-60.0000</string> <string name="longitude_def">-180.0000</string>
<string name="longitude_summary">Ground station longitude from -180 to 180</string> <string name="longitude_summary">Ground station longitude from -180 to 180</string>
<string name="height">Height:</string> <string name="height">Height AMSL: </string>
<string name="height_def">64</string> <string name="height_def">51.0m</string>
<string name="height_summary">Ground station height in meters AMSL</string> <string name="height_summary">Ground station height in meters AMSL</string>
<string name="menu_update_location">Update location</string> <string name="menu_update_location">Update location</string>
+19 -2
View File
@@ -13,8 +13,25 @@
<item name="android:statusBarColor">@android:color/transparent</item> <item name="android:statusBarColor">@android:color/transparent</item>
</style> </style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" /> <style name="DrawerHeader">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">@color/colorDrawerText</item>
</style>
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat" /> <style name="DrawerHeader.Title">
<item name="android:textAppearance">@style/TextAppearance.AppCompat.Title</item>
<item name="android:textSize">32sp</item>
</style>
<style name="DrawerHeader.Item">
<item name="android:textAppearance">@style/TextAppearance.AppCompat.Medium</item>
<item name="android:textSize">18sp</item>
</style>
<style name="DrawerHeader.Value">
<item name="android:textAppearance">@style/TextAppearance.AppCompat.Large</item>
<item name="android:textSize">24sp</item>
</style>
</resources> </resources>
-29
View File
@@ -1,29 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="Ground station location">
<SwitchPreference
android:defaultValue="true"
android:disableDependentsState="true"
android:key="DEVICE_LOCATION"
android:summary="@string/device_location_summary"
android:title="Use device location" />
<EditTextPreference
android:defaultValue="@string/latitude_def"
android:dependency="DEVICE_LOCATION"
android:key="LATITUDE"
android:summary="@string/latitude_summary"
android:title="@string/latitude" />
<EditTextPreference
android:defaultValue="@string/longitude_def"
android:dependency="DEVICE_LOCATION"
android:key="LONGITUDE"
android:summary="@string/longitude_summary"
android:title="@string/longitude" />
<EditTextPreference
android:defaultValue="@string/height_def"
android:dependency="DEVICE_LOCATION"
android:key="HEIGHT"
android:summary="@string/height_summary"
android:title="@string/height" />
</PreferenceCategory>
</PreferenceScreen>
+1 -2
View File
@@ -34,8 +34,7 @@ ext {
navigation = '2.1.0' navigation = '2.1.0'
lifecycle = '2.1.0' lifecycle = '2.1.0'
work = '2.2.0' work = '2.2.0'
paging = '2.1.0' room = '2.2.1'
room = '2.2.0'
retrofit = '2.6.2' retrofit = '2.6.2'