This is an Android showcase project based on a simple feature using GitHub API.
The main goal of this project is to implement the best practices on how to start an app, as recommended by Google and seen here:
- App startup time
- App Startup
- Splash screens
- Remove the custom splash screen Activity
- Use Room to fetch and cache data
- Placeholder UI
- Branded launch
This project hosts two sample apps in separate repository branches.
Branch | Description |
---|---|
main | Default sample for this project. Uses profile feature as first loading screen. |
lazy-initialization* | Uses an static feature as first loading screen and implements lazy initialization of other components. |
* work in progress
App Startup is a multi-module project built with MVVM Architecture.
.
├── app # Project sample (android-application)
├── buildSrc # Dependency management with Kotlin DSL
├── core
│ ├── network # Network layer abstraction (android-library)
│ ├── network-impl # Network layer implementation (android-library)
│ ├── splash-screen # Splash screen configurations (android-library)
│ └── ui # Theme and components (android-library)
└── feature
├── menu* # Feature which doesn't depends on network requests (android-library)
└── profile # Feature which depends on network requests (android-library)
* the feature:menu module is used only on lazy-initialization variation
It provides a performant way to initialize components and explicitly define their dependencies.
To automatically initialize components at startup, you must define a component initializer for each component that the app needs to initialize.
This can be done by implementing the Initializer<T> interface and setting the manifest entries.
Since this sample project uses the abstract network module to consume the GitHub API, the profile feature module initialization shall depend on the network-impl module to provide of a concrete implementation of a Retrofit interface.
ProfileInitializer
class ProfileInitializer : Initializer<Unit> {
override fun create(context: Context) {
ProfileFeature.init(NetworkImpl)
}
override fun dependencies(): List<Class<out Initializer<*>>> {
// This is only called after NetworkInitializer is initialized
return listOf(NetworkInitializer::class.java)
}
}
NetworkInitializer
class NetworkInitializer : Initializer<Network> {
override fun create(context: Context): Network {
return NetworkImpl
}
override fun dependencies(): List<Class<out Initializer<*>>> {
// No dependencies on other components
return emptyList()
}
}
Includes an into-app motion at launch, a splash screen showing your app icon, and a transition to your app itself.
As recommended by Material Design, a branded indicator is displayed until a placeholder UI loads.
// feature:profile
override fun onCreate(savedInstanceState: Bundle?) {
showSplashScreen { viewModel.uiState.value is ProfileViewModel.UiState.Default }
super.onCreate(savedInstanceState)
// ...
}
// core:splash-screen
fun Activity.showSplashScreen(condition: KeepOnScreenCondition? = null) {
installSplashScreen().run {
condition?.let { ::setKeepOnScreenCondition }
setOnExitAnimationListener { /** Custom animation */ }
}
}
It's also possible to keep the splash screen on-screen for longer periods by setting a condition on an observable value such as StateFlow or LiveData.
showSplashScreen { viewModel.uiState.value is ProfileViewModel.UiState.Success }
In this approach the Placeholder UI is not used, since the first screen will only be shown to the user when its contents has fully loaded.
Also known as skeleton screen. It shows a content placeholder while network-based data is being fetched, instead of displaying a blank screen or a default loading animation.
This was done using Accompanist-placeholder, a library for Jetpack Compose.
As recommended here and here, the placeholder is most likely to be shown only when a user opens the app for the first time. The next time this user returns to the app, we can show a cached content while a more recent content is loaded.
- Unit tests
- UI-State layer (ViewModel)
- Data layer (Repository and Data Sources)
- UI tests
- 🚧 Work in progress 🚧
- Baseline Profiles
- Add Room to cache network data.
- Animated icon in splash screen.
- lazy-initialization variation branch.
- UI tests.
- GitHub Actions.