Skip to content

Tomekkk/PixabayClient

Repository files navigation

Requirements

The PixabayClient app uses Pixabay API. The API requires a key to search images. The key can be obtained from Pixabay API's documentation by registering in Pixabay. Add the key to ./local.properties file as pixabay.api.key=KEY property. The required minimum API level is 23.

Features

  • Home screen with search interface of Pixabay API
  • User-friendly search results presented on StaggeredGrid that dynamically adjust cells to the available space during screen orientation changes
  • Dynamic pages loading while scrolling
  • Caching search results in a local database
  • Load and cache images on-device storage
  • Image details screen with larger image and stats accessible from the list
  • Dynamic theming based on the system theme (light or dark)
video.mp4

Architecture

The PixabayClient app is built on top of layered architecture that follows uni-directional data flow, drives the separation of concerns and focuses on making testing easier. MVVM pattern is used to separate the UI and business logic. The architecture has clearly defined UI, data and domain layer reflected in data, domain ad ui packages. The data layer expose interfaces that can be easily faked in tests. A dependency injection pattern is used to provide the dependencies to the abstract components making them easier to maintain and test. Coroutines and flows are used to handle asynchronous operations and provide data streams. Taking into account the size of the project it was implemented as a single module.

Data Layer

The data layer is built with a Repository pattern that exposes data stored in the Room database fetched from API. Defined interfaces provide a clear abstraction for the data sources. Each search results are paged by 40 items per page and loaded from the network with the help of Paging 3.

Cache

Pixabay API requires caching requests for 24h to avoid unnecessary network calls. The app uses RemoteMediator implementation to fetch, cache and invalidate the search results for a given query. The cache is cleared for a given query when the user resends the search request and data stored in the cache is older than 24 hours.

Validate the cached data and initially refresh it when needed, load next pages from network and store them in the database cache. The mediator is used by the PagingSource to provide the data to the UI layer. Based on the state of the anchor position(scroll position) and currently loaded pages, the mediator decides whether to load the next page and how to append new items to the stream presented in the UI.

Domain Layer

Following the Clean Architecture principles the domain layer is built with use cases that provide better separation of concerns. The use cases use repository interfaces defined in the data layer. Data models are converted to domain models in the domain layer. The use cases are used by the view models to provide the data to the UI layer.

UI Layer

AAC ViewModels are used to manage UI state in a lifecycle conscious way with the support of persisting it through configuration changes. Jetpack Compose is used to build the UI layer. The UI is built with a single activity. Navigation was implemented with Jetpack Navigation Hilt extension is used to provide the ViewModel instances in composable functions.

Testing

In favor of fakes over the mocks, dependencies of repositories, data sources, mediators or time/cache providers are defined as abstractions. Data/business logic layers are unit tested with JUnit, Mockk and Robolectric. DBCachedImagesResultsMediatorTest is an example of instrumented test that checks the behavior of the mediator interacting with Room database.

Continuous Integration

CI is implemented with GitHub Actions. The on-pull-request.yml workflow has defined two jobs responsible for running the tests and linting the code on every pull request. Both jobs run in parallel.

Dependencies

All the libraries and plugins used in the project are listed in the libs.versions.toml file. Some of the libraries used in the Application are:

  • Dagger Hilt - Dependency injection framework recommended for Android projects
  • Glide - Image loading with cache mechanism focused on smooth scrolling
  • Jetpack Compose - Modern UI toolkit
  • Jetpack navigation - Navigation component with support for deep linking and jetpack compose
  • Kotlin Coroutines - Asynchronous programming
  • Kotlin Flows - Asynchronous data streams
  • Material 3 - Material Design 3 components
  • Mockk - Mocking library for Kotlin
  • Moshi - API responses JSON parsing
  • Paging 3 - Pagination with Jetpack Compose and Room integrations
  • Retrofit - Type-safe HTTP client
  • Robolectric - Unit testing framework
  • Room - Cache Database with Paging 3 integration

About

Case study with Pixabay API

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages