Android exercise, fetch open API data and show it in list and detail pages.
- fetch data from Singapore government open data
- the mobile data usage data, url pattern is
https://data.gov.sg/api/action/datastore_search?resource_id=a807b7ab-6cad-4aa6-87d0-e283a7353a0f&limit=5&offset=6
- the mobile data usage data, url pattern is
- show every year mobile data usage volume in a list
- the raw data is count by every quarter of year, like 2020-Q1
- show a dropdown image to show that at least one quarter volume is less than the last quarter
- (optional) use data cache
- well designed
- updated Android suite: kotlin, jetpack
- well tested support by test framework
It will be two pages app, list and detail screen.
- List page: show every year mobile data usage volume, can switch between normal style and card style.
- Detail page: show one year usage, with the quarter data usage volume
- MainActivity
- .volumelist : list page
- .volumedetails : details page
- .data : pojo define, fetch remote data and store in local sqlite
- .util : constant define, tools etc
.
├── AndroidManifest.xml
├── java
│ └── com
│ └── yuman
│ └── anotherexercise
│ ├── MainActivity.kt
│ ├── ServiceLocator.kt
│ ├── VolumeApplication.kt
│ ├── data
│ │ ├── IVolumeRepository.kt
│ │ ├── QuarterVolumeItem.kt
│ │ ├── VolumeRepository.kt
│ │ ├── YearVolumeItem.kt
│ │ ├── local
│ │ │ ├── VolumeDao.kt
│ │ │ └── VolumeDatabase.kt
│ │ └── remote
│ │ ├── DataUsageResponse.kt
│ │ └── RemoteDataSource.kt
│ ├── util
│ │ ├── FetchDataStatus.kt
│ │ ├── StaticDefine.kt
│ │ └── VolleySingleton.kt
│ ├── volumedetails
│ │ └── VolumeDetailsFragment.kt
│ └── volumelist
│ ├── VolumeListAdatper.kt
│ ├── VolumeListFragment.kt
│ └── VolumeListViewModel.kt
└── res
├── drawable
│ ├── ic_launcher_background.xml
│ └── ic_trending_down.xml
├── drawable-v24
│ └── ic_launcher_foreground.xml
├── layout
│ ├── activity_main.xml
│ ├── fragment_volume_details.xml
│ ├── fragment_volume_list.xml
│ ├── switch_item.xml
│ ├── volume_cell_card.xml
│ └── volume_cell_normal.xml
├── menu
│ └── main_menu.xml
├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
├── mipmap-hdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
├── mipmap-mdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
├── navigation
│ └── nav_graph.xml
└── values
├── colors.xml
├── strings.xml
└── styles.xml
Restruct the project to support unit test, such as constructor injection to add test double, service locator to bypass singleton creation both in release and test environment.
- to run test in console
./gradlew testDebugUnitTest --continue
./gradlew connectedDebugAndroidTest --continue
the report will be in folder: ./app/build/reports/
- to get test coverage report
./gradlew testDebugUnitTestCoverage
(need the device or emulator is connected)
the report will be in folder: ./app/build/reports/
Compair with Our Android 2020 development stack, which list the common but modern libraries.
- Ktlint
- Android Lint
- Lin
- Ribbonizer
- Play publisher
Not used stand-alone lint tools above, just used Android Studio integrated one:
./gradlew lint
- Retrofit
- OkHTTP
- Gson
For the purpose of practice, chose using Google's Volley without OkHttp. Actually Retrofit+OkHttp is common choice for me.
- Room
- SQLDelight
- Dexter
No need in this project
- Data Binding
- Lifecycle Observer
- Appcompat
- ConstraintLayout
- Glide
- Renderers
- Calligraphy
- Material Components
- Snacky
- Lottie
some of them are no need in this project
- Kotlin
- Coroutines
- Timber
- Libphonenumber
- OneSignal
- Kodein
- ThreeTenABP
- Crashlytics
- Arrow
- Leakcanary
emmm, crash reporter, performance tools or even logger tool should be included
- JUnit
- Shot
- Kotlin Snapshot
- Kotlin Test
- Mockito
- MockWebServer
- Robolectric
- Espresso
- Barista
- Jacoco
- Bitrise
- LiveData
- Navigation
- ViewModel
- WorkManager
- CameraX
When doing instrumentation tests in Android Studio, it may fail with message below
java.lang.UnsupportedOperationException: Failed to create a Robolectric sandbox: Android SDK 29 requires Java 9 (have Java 8)
one solution is to set runtime JRE environment to Java 9 in Android Studio:
Run -> Edit Configurations... -> in popup window, select the Android JUnit test configuration, specify the JRE to new folder
Fixed by changing "targetSdkVersion 29" to "targetSdkVersion 28", it will avoid the problem above.
The reason is it will change to use older Robolectric lib, and it will not throw out exception just a warning.
- refine build script
- test coverage report
- dev ops integration
- more test: server connection mock, integration test UI check, monkey test etc
- play with: paging, viewpage2 etc
- maybe: i18n, separate landscape view, controller style
- coding, the app is functionally workable
- unit test and simple function test
mainly did everything in Android Studio IDE environment, so tested in limited environment