/WeatherApp

MVVM, databinding, coroutines, clean architecture

Primary LanguageKotlin

WeatherApp

This is a simple Android app written in Kotlin that displays the current weather for a input location.

Here Destination Weather API is used to fetch the current weather information

Libraries used:

Architecture

This app follows Clean architecture by Uncle Bob

The code is divided into 3 main layers: Data, Domain, and Presentation

Data

Networking

The Data layer is responsible for fetching data from the API and supplying it to the Domain layer.

Retrofit is used with Moshi to fetch and deserialize the response from the API. A set of response objects (DTOs) are included in this layer. They map 1-1 to the API contract

A OkHttp Interceptor handles authentication with a simple API Key-based system.

OAuth2.0 could be a future improvement

Repository

A simple in-memory repository is used for holding the data returned by the API.

The repository supports synchronous and asynchronous fetching, as well as refreshing from the API.

A simple Mapper class is used to map from the response objects (DTOs) to the domain entities

Domain

The domain layer is responsible for handling data flow and business logic

A set of Entities are used in this layer. These models more accurately map to the app business requirements

UseCases are included in this layer. They use a suspend function to allow the presentation layer to interface via Kotlin coroutines

Presentation

The presentation layer is responsible for displaying the data returned from the Domain layer to the user.

The MVVM pattern is used here to divide the UI logic from the Android framework. The View (Activity currently) is designed to be as "dumb" as possible.

The ViewModel exposes a UiState LiveData stream that continually emits based on external events like user input and network responses. The UiState should be a nearly direct representation of the UI on the screen. Some "sub-UiStates" were created to standardize this approach (ImageUiState, AnimationUiState, TextInputUiState). This approach was inspired by Jetpack Compose

viewModelScope CoroutineScope is used to easily handle cancelling network calls based on the Android Activity lifecycle

DataBinding is leveraged to minimize logic and boilerplate in the View. Most data from the ViewModel's UiState is directly mapped to the Android Views

Animations

Some animations were added using Lottie to portray the current weather conditions. A small set of animations were added; this could be expanded to include all possible weather conditions

To view the various animations available, pull out the debug drawer from the very left side of the screen

Continuous Integration (CI)

Github Actions is used to build and run unit tests on each commit on the master branch

See this build for an example https://github.com/mrea1/WeatherApp/runs/862106667

Future enhancements could include:

  • Continuous Delivery (CD) using a framework like Firebase App Distribution or HockeyApp (now Visual Studio App Center)
  • Automated UI testing using a framework like Waldo or Appium

Testing

A small set of unit tests are included. The architecture in the app allows for easy unit testing.

JUnit 4 is used currently. A future improvement could be to use JUnit 5.

Mockk is used to mock dependencies in unit tests. It works well with coroutines, in contrast to Mockito

UI testing with Espresso is not really needed here, since the bulk of UI logic is easily unit tested on the ViewModel layer