Skip to content

Kotlin Multiplatform Mobile demo for Android and iOS. App for viewing Cat pictures

License

Notifications You must be signed in to change notification settings

MartinRajniak/CatViewerDemo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

83 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CatViewerDemo

Check

Android demo iOS demo
Android Demo iOS Demo

Kotlin Multiplatform Mobile demo for Android and iOS. App for viewing Cat pictures from Cats API.

This sample showcases:

Usage

I leave here some notes that might help anyone who would like to build it themselves.

Cats API key

The project is using a property named catsApiKey to retrieve the key for the API.

You can provide it through gradle.properties, for example.

Kotlin Multiplatform Mobile setup

You should follow KMM setup to build the application, both for Android and iOS.

Google Services

Google Services configuration file is required for Crashlytics, which the app uses to report issues to the authors. If you want to build and run the app, you need to create your own Firebase project:

  1. Create a project on Firebase console.
  2. Add applications using the package name eu.rajniak.cat.android for Android and eu.rajniak.cat.iosApp for iOS.
  3. Follow the instructions and download the configuration file to the appropriate folder. Refer to setup Android or setup iOS for further details.
  4. Enable Crashlytics on the Firebase console.

In case you don't want to create a new Firebase project, you can still build applications with dummy configuration files. Keep in mind that applications with this config will not run.

This guide is inspired by code-with-the-italians/bundel.

Dependency updates

To keep dependencies updated Version Catalog Update Plugin is used.

All you need to do is to run ./gradlew versionCatalogUpdate.

Overview

The goal of the exercise was to build Kotlin Multiplatform Mobile applications for Android and iOS, with only UI written in platform-specific code (ComposeUI and SwiftUI).

Everything from ViewModel to Repository and data sources is shared.

Architecture

Architecture follows the standard blueprint proposed in Guide to app architecture.

Shared module

The shared module consists of Kotlin Multiplatform code that I use to share business and presentation logic between Android and iOS.

ViewModel

CatsViewModel is the class that UI platform-specific code interacts with. It prepares cats data displayed in the UI. It also listens to the actions that happen in UI.

It extends SharedViewModel that provides shared scope for coroutine work. I took inspiration from MOKO MVVM library, which I plan to use instead once there is more time.

Repository

CatsStore is responsible for providing Cats model data. It fetches data from CatsApi and to map it to model data used in application.

In the future, I might use the Mapper pattern for mapping data from external systems to domain models.

Data from CatsApi is intentionally not persisted, to provide up-to-date results.

CatsApi

CatsApi uses Ktor to fetch data from Cats API.

SettingsStorage

SettingsStorage provides platform specific implementations for key value storage. On Android it is Datastore.

CatViewerServiceLocator

All dependencies are provided by CatViewerServiceLocator. For such a small application, it perfectly serves its purpose.

For larger applications, I would recommend Hilt (DI library).

Android platform-specific UI

MainActivity is a single activity in the application as the only application entry point. Even with more screens, I would still recommend using single activity as screens can be represented as composable functions now.

CatsUI file and composable function currently represent the only screen in the application. I divided the file into multiple functions for clarity.

iOS platform specific UI

CatsView is single screen displaying list of Cats. Cats are represented by CatItem view. For filtering, view has been created and is displayed as a sheet.

CatsStore serves as adapter between Kotlin Flow world and SwiftUI.

Tests

Shared code has one test file with a bunch of basic unit tests. You can find them in CatsTest.

I test the shared code through the ViewModel interface and I use Fakes for external systems like networking and IO.

It allows us to test most of the business logic from a single interface. Once I add more logic to tested objects, I might need to write more isolated tests.

There is also one UI instrumentation test in the Android application module. It runs with dummy ComponentActivity provided by the test library. It allows us to test the UI in isolation.

Special thanks

This project was way simpler thanks to all the resources, libraries and projects I was able to find on this topic.

CatsAPI

First and foremost, thanks to the people that created and maintained a free public service API that I could use to showcase KMM.

John O'Reilly

His repositories that showcase Kotlin Multiplatform were crucial to my work.

Especially, repository that demonstrates paging. I could not use the same multiplatform paging library (time constraints), but I want to try it in the future.

Touchlab

People at Touchlab and all the resources they provide publicly were especially helpful for my understanding of how Kotlin native threading works.

Jetbrains and community

During the project, I was using Apple M1 Silicon and with it arm64 simulators. Support in libraries is getting better, but the community on #kotlin-lang Slack channel, was extremely helpful when I was fighting with this.

Others

Special thanks also to all people that share their solutions around Kotlin Multiplatform. It is hard to find any up-to-date resources, so every single one of them counts.

Thanks to all the Kotlin Multiplatform libraries out there. I used:

TODO

Some things were left undone.

GIFs

Coil on Android helps us with displaying GIFs, but this has not yet been implemented on iOS.

Caching

Coil on Android is already caching images on disk, but there is no caching of images on iOS.

Error Handling

There is almost no error handling implemented at the moment.

It would be nice to show errors when image loading fails, there is a network issue, etc.

Full-screen view

It would be nice to be able to display images on full screen.

I could showcase Navigation with Compose, since I would have another screen.

Continuous Integration

I believe that even when developing a project alone, Continuous Integration service can help.

I would at least know that the build, tests and static analysis run with every new commit.

Another advantage is that I can be sure that someone else (another machine) can build it.

GitHub should be able to provide this functionality.

UI improvements

There is a lot of work on UI.

One thing that stands out is filtering, I don't think it is intuitive at this point. But it is there primarily to show work with Flows, so it is OK for now.

Bugs

There are probably a lot of bugs, but one stands out.

Pagination, loading of new images is working nicely. But only when the user scrolls to the bottom of the list.

But new images are not loaded when the user gets to the bottom by filtering.