Skip to content

Repository files navigation

Kotlin Mobile Multiplatform App (Android & iOS)

One Code To Rule Them All. Application example using Kotlin Multiplatform and MVVM pattern for both platforms.

Is used:

  • layered clean architecture
  • DI (Kodein)
  • coroutines
  • livedata
  • ktor
  • serialization
  • mockk
  • detekt, ktlint
  • unit tests and jacoco

Presentation layer (Android & iOS)

On both platforms (Android and iOS), we only need to implement an observer in which to process states. Further implementation on Android (Kotlin) and iOS (Swift):

Android

classMainActivity : AppCompatActivity() {
privatelateinitvar viewModel:IndexesViewModelprivatevar adapter:IndexesAdapter=IndexesAdapter { viewModel.getQuote(it.ticker) }
overridefunonCreate(savedInstanceState:Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recycler.adapter = adapter
viewModel =ViewModelProviders.of(this).get(IndexesViewModel::class.java)
observeViewState()
viewModel.getMajorIndexes()
}
privatefunobserveViewState() {
viewModel.getViewData.addObserver { updateViewState(it) }
}
privatefunupdateViewState(state:IndexesViewState) = runOnUiThread {
when (state) {
isLoading-> {
Toast.makeText(this, "Loading...", Toast.LENGTH_SHORT).show()
}
isError-> {
Toast.makeText(this, state.message, Toast.LENGTH_LONG).show()
}
isShowMajorIndexes-> {
adapter.items = state.indexes
}
isShowQuote-> {
Toast.makeText(this, state.quote.dayLow +" - "+ state.quote.dayHigh, Toast.LENGTH_LONG).show()
}
}
}
}

iOS

classViewController:UIViewController,UITableViewDataSource,UITableViewDelegate{@IBOutlet weak vartableView:UITableView!privatevarviewModel:IndexesViewModel!internalvarindexes:[Index]=[]overridefunc viewDidLoad(){
super.viewDidLoad()
tableView.dataSource =self
tableView.delegate =self
viewModel =IndexesViewModel()observeViewState()
viewModel.getMajorIndexes()}func observeViewState(){
viewModel.getViewData.addObserver{(state)inself.updateViewState(state: state as!IndexesViewState)}}func updateViewState(state:IndexesViewState){switch state {case is Loading:
view.displayToast("Loading...")case is Error:
view.displayToast("Error")case is ShowMajorIndexes:letsuccessState= state as!ShowMajorIndexesupdate(list: successState.indexes)case is ShowQuote:letsuccessState= state as!ShowQuote
view.displayToast(successState.quote.dayLow +" - "+ successState.quote.dayHigh)default:break}}...deinit{
viewModel.onCleared()}}

Presentation Layer - ViewModels (Shared Code)

This layer is shared by Android and iOS, and this is developed on Kotlin. Here is where we have to call the different use-cases of the domain layer. To make the call async we are using kotlin coroutines and flow.

classIndexesViewModel : BaseViewModel() {
privateval getIndexesUseCase by Injector.instance<GetIndexesUseCase>()
privateval getQuoteUseCase by Injector.instance<GetQuoteUseCase>()
var getViewData =MutableLiveData<IndexesViewState>(Empty)
fungetMajorIndexes() = launchInMain {
getIndexesUseCase()
.onStart { getViewData.postValue(Loading) }
.flowOnBackground()
.catch { getViewData.postValue(Error("Something went wrong")) }
.collect { getViewData.postValue(ShowMajorIndexes(it)) }
}
fungetQuote(symbol:String) = launchInMain {
getQuoteUseCase.invoke(symbol)
.onStart { getViewData.postValue(Loading) }
.flowOnBackground()
.catch { getViewData.postValue(Error("Something went wrong")) }
.collect { getViewData.postValue(ShowQuote(it)) }
}
}

Domain Layer — Models & UseCases (Shared Code)

In this layer, we defining the models and all the use cases that we need for our application.

Data Layer — Repository Pattern (Shared Code)

For this layer we are using a repository pattern. We defining the entity models and all source of our data

For networking we are using Ktor and for JSON deserialisation Kotlinx serialization.

Running unit tests

  • Android test: ./gradlew testDebugUnitTest
  • Common test on iOS (need run Simulator iPhone 8): ./gradlew iosUnitTest

Running the app

To run the application use the same tools you use in Android and iOS. Just open the project with Intellj/Android Studio for the Android project and XCode for the iOS one.

Screenshots

AndroidiOS
android-appios-app

About

👨‍💻 Kotlin Mobile Multiplatform App (Android & iOS). One Code To Rule Them All. MVVM, DI (Kodein), coroutines, livedata, ktor, serialization, mockk, detekt, ktlint, jacoco

Topics

Resources

Stars

33 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages