Expertise utilizing KMP in manufacturing apps for a yr. | by Harshith Shetty | Jul, 2022


  • 10 Million+ MAU(s)
  • Completely steady. Crash-free periods: >99.75 %
  • >70% code reuse.
  • 24 cell devs (14 Android + 10 iOS)
  • Kotlin model presently: 1.6.21
  • Outcomes into higher segregation of frequent modules from particular platform app repository(android, ios, internet, backend app, and so forth).
  • It will preserve frequent KMP tooling, plugins, libraries, and so forth away from current/new apps.
  • This makes it straightforward for current/new apps to plug and play frequent code as a third-party library as a substitute of establishing frequent KMP tooling, plugins, libraries, integration, and so forth in platform particular app repository.
  • You’ll be able to share frequent KMP code as libraries for the android and ios apps by way of maven.
  • Publishing will output the frequent KMP code into all of the targets(android, ios, js, and so forth) and maven will host the artifacts.
  • The host apps will simply load their very own platform artifacts from the maven similar to we load a third-party library by way of maven in Gradle.
  • For native improvement, maven has a neighborhood repository which hosts it on the identical machine for simple sharing artifacts between initiatives on the identical machine with only a single Gradle command: “publishToMavenLocal”
  • You should use GitLab to make it tremendous straightforward because it has a maven repository out of the field. So the git repository and the maven packages will likely be accessible from a single GitLab repository.
  • By including distant maven configuration in “KMP Repository”, you possibly can straight use the “publish” Gradle process to construct and push the artifacts on the maven.
  • On the App Repository aspect, the identical maven configuration will likely be wanted to tug the libraries from maven.
  • Instance: Maven configuration to be added right here.
  • The Worst a part of KMP is that anybody can construct frequent KMP code like they write Kotlin in android and it’ll run flawlessly in Android.
  • It’s worst as a result of it should crash in iOS on account of Kotlin Native guidelines like freezing of objects in multithreading and so forth so a PoC ought to be made to grasp what is feasible and what’s to not make tips and guidelines for improvement in frequent code. For e.g: InvalidMutabilityException
  • Study in regards to the guidelines from right here. Create a listing of tips in order that different builders can observe them when engaged on any new/current KMP options. Bonus: Have added some tips at finish of the weblog for reference.
  • Count on-actual provides a very simple approach of making platform-specific entry but it surely has limitations like the identical constructor signature.
  • Has scalability points to help new platform dependencies. For e.g: A brand new platform may have some totally different constructor dependencies.
  • Additionally, you’ll need to make “precise class” from the Kotlin file solely.
// commonMain
count on class NetworkGateway(debug: Boolean) {
val consumer: HttpClient
// androidMain
precise class NetworkGateway precise constructor(debug: Boolean) {
precise val consumer: HttpClient
get() = TODO("Not but applied")
// iosMain
precise class NetworkGateway precise constructor(debug: Boolean) {
precise val consumer: HttpClient
get() = TODO("Not but applied")
  • Utilizing interfaces as a substitute will allow you to freely create the implementation with any platform-specific constructor.
  • You’ll be able to implement the interface in a platform-specific language like Swift for iOS. So you possibly can ship dependency from platform sides too.
  • So you possibly can go current platform dependencies implementing the interfaces and passing by way of DI to frequent KMP code with extra freedom.
// Utilizing interface
interface INetworkGateway {
val consumer: HttpClient

// androidMain or from Android App Repository.
class AndroidNetworkGateway(
personal val debug: Boolean,
personal val interceptors: Record<Interceptor>,
personal val networkInterceptor: Record<Interceptor>
) : INetworkGateway {
override val consumer: HttpClient
get() = TODO("Not but applied")

// iosMain
class IOSNetworkGateway(personal val debug: Boolean) : INetworkGateway {
override val consumer: HttpClient
get() = TODO("Not but applied")

  • Even after adhering to Okay/N guidelines, there’s at all times room to overlook some guidelines or some circumstances, so there ought to be a plan to accommodate them.
  • Suppose a standard characteristic is already rolled out on android and whereas integrating it into iOS, there is a matter and the code must be fastened.
  • Now the repair will impression each android and iOS on the subsequent KMP library launch. So to reduce the impression, if unit assessments are already current after no matter adjustments we do for Okay/N, we are able to ensure that it’s not breaking any current stream whereas updating code to stick to guidelines for iOS.
  • Writing Integration assessments for iOS will likely be significantly better as it should create a regression suite for Okay/N rule crashes.
  • Publishing a standard code regionally and together with it within the precise app repository for integration testing and rebuilding will sluggish you down.
  • So if that you must check it E2E then you possibly can join the shared code within the testing host modules which can be already made in a brand new KMP mission and use that to check any integration earlier than native/distant publishing.
  • This will likely be a lot quicker to work and even debug points.
  • You’ll be able to create a standard dependency file and totally different platform dependency recordsdata.
  • For e.g: CommonDependencies , AndroidDependencies and so forth.
  • This allows you to preserve frequent platform third-party libraries in sync on each KMP Repository and platform app Repository.
  • Don’t use vars for bigger scopes in Widespread code. Use MutableStateFlow as a substitute. For instance, for sophistication scoped variables. So goes with out saying, use vals largely. To keep away from: InvalidMutabilityException
class PersonViewModel{
personal var loading:Boolean = false //Do not
personal val loading = MutableStateFlow(false) //Do
  • Use init {} block after declaring all class variables. That is to keep away from anybody making a coroutine in init, which is able to make the entire class occasion freeze and end in throwing an exception on the loading discipline declared after it.
class PersonViewModel{

init {

} //Do not

personal val loading = MutableStateFlow(false)init {

} //Do

  • Passing an current UserRepository in platform app to frequent KMP Code as a substitute of making it from scratch in frequent code.
  • There may be a number of implementations of a dependency within the KMP repository and platform repository. So switching or A/B may be achieved on the platform degree as per wants.



Leave a Comment