Kotlin Multiplatform Router for Android and iOS

Overview

Kompass

A powerful Kotlin Multiplatform Router for Android and iOS


GitHub top language Build Status Bintray GitHub last commit Gitter

Support

I am happy to help you with any problem on gitter
Feel free to open any new issue!

What Kompass can do for you

  • Perfect fit for MVVM, MVI, MVP, MVX architectures
  • Powerful routing concept that targets multiple platforms like Android, JVM & iOS
  • Easy to use API's
  • Highly configurable implementations

Android

  • Flexible routing with fragments
  • Built in solution for passing arguments to fragments
  • Very easy support for transitions/animations
  • No XML configuration
  • Built in DSL to configure the FragmentRouter
  • Survives configuration changes
  • Can restore the "routing stack" after process death

What Kompass can't do for now

While the core module is currently built and published for multiple platforms (JVM, iOS), there are no default Router implementations for any other platforms than Android yet. Those are currently "work in progress". Kompass can still be used as a common API for routing by providing custom implementations of a Router for your platform!

Setup

Step 1: Add the repository

Artifacts are linked to jCenter. Add jCenter repository to your root build.gradle

build.gradle

  allprojects {
     repositories {
        jcenter()
     }
  }

Step 2: Add the dependency (Multiplatform)

build.gradle.kts

kotlin {
    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation("io.sellmair:kompass-core:0.2.0-alpha.5")
            }
        }
        
        /* Optional Android module */
        val androidMain by getting {
            dependencies {
                implementation("io.sellmair:kompass-android:0.2.0-alpha.5")
            }
        }
    }
}

Step 2: Add the dependency (Android Only)

build.gradle.kts

dependencies {
    implementation("io.sellmair:kompass-android:0.2.0-alpha.4")
}

Optional Step 3: (Android: Highly encouraged) Enable Kotlin's Android extensions (with @Parcelize)

build.gradle.kts

plugins {
    // ...
    id("org.jetbrains.kotlin.android.extensions")
}

// ...

// Currently still necessary for @Parcelize annotation
androidExtensions {
    isExperimental = true
}

Usage

Example

I recommend having a look at the example app built with Kompass



Gif



Defining routes

Routes can easily be represented by data classes. Let's say your App has three routes that you might want to display: A LoginRoute, ContactListRoute and a ChatRoute:

sealed class AppRoute : Route, Parcelable

@Parcelize
class LoginRoute: AppRoute()

@Parcelize
data class ContactListRoute(val contacts: List<Contact>): AppRoute()

@Parcelize
data class ChatRoute(val contact: Contact): AppRoute() 

All the arguments necessary to display a certain route should be present in the route itself. The example above uses the @Parcelize feature from the Kotlin's Android extensions

Creating a router instance (Android)

A FragmentRouter for Android can be configured quite easily by using the built in DSL for configuration.

router = FragmentRouter {
            transitions {
                register(LoginToContactListTransition())
                register(ContactListToChatTransition())
            }
            routing {
                route<LoginRoute> { LoginFragment::class }
                route<ContactListRoute> { ContactListFragment::class }
                route<ChatRoute> { ChatFragment::class }
            }
        }

The above DSL shows two configurations:

  • transitions: configures animations/transitions that should be running when routing
  • routing: configures which Fragment should be displayed for a certain route

Setting up a router instance (Android)

A FragmentRouter needs a ViewGroup to place the fragments in. This can be setup like this:

class MainActivity : AppCompatActivity(), KompassFragmentActivity {


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        router.setup(savedInstanceState, R.id.container)
    }


    override fun onBackPressed() {
        router.popRetainRootImmediateOrFinish()
    }

}

Please note: In order to call the setup method, one needs to either implement KomapssFragmentActivity or KompassFragment!

Routing (Simple push)

Let's assume that the user taps on a certain contact in the contact list displayed by the ContactListRoute:

class ContactListViewModel {
 
    private val router = TODO("Maybe use DI?")
 
    fun onContactClicked(contact: Contact) {
        router.push(ChatRoute(contact))
    }

}

The code above will push the ChatRoute onto the "routing stack" and results in the ChatFragment being shown. Popping the "routing stack" will result in the ContactListFragment being displayed again.

Routing (Replacing the current route)

Let's assume the user successfully logged into your app. This should result in the current LoginRoute being replaced by the ContactListRoute

class LoginViewModel {

    private val router = TODO("What about Dagger?")
    
    fun onLoginSuccessful(user: User) {
        router.replaceTopWith(ContactListRoute(user.contacts))
    }
}

Wrapping multiple instructions into one lambda block will bundle them to one single operation on the routing stack. So you could alternatively write something like

fun onLoginSuccessful(user: User) {
    router { pop().push(ContactListRoute(user.contacts)) }
}

Routing (Arbitrary)

Kompass supports arbitrary routing: A instruction to the router is nothing more than a function from a list of routes to a new list of routes. Let's say your app would like to remove all ChatRoute with a certain contact

fun removeContactFromStack(contact: Contact) {
     router {
        with(filter { it.route.contact == contact })
     }
     
     //or
     
     router.plainStackInstruction { filter { it.route.contact == contact } }
}

Receiving the current route inside a Fragment

Accessing the route from within the any Fragment implementation is easily done by conforming to the KompassFragment interface:

class ContactListFragment : Fragment(), KompassFragment {
   
    override val router: FragmentRouter<AppRoute> = TODO() 
   
    private val route: ContactListRoute by route()
    
    override fun onCreate(savedInstanceState: Bundle?) {
        val contacts = route.contacts 
        
       //...
    }

}

Fragment Transitions

In order to support animations (fragment transitions) when routing you just need to implement a FragmentTransition. Example: Your chat app should show a Slide transition when going from the ContactListFragment to the ChatFragment and back. Simply implement the transition, check for your constraints and apply the transitions to the fragment. It is also possible to apply generic constraints to your transition using the GenericFragmentTransition API.

class ContactListToChatTransition : FragmentTransition {
    @SuppressLint("RtlHardcoded")
    override fun setup(
        transaction: FragmentTransaction,
        exitFragment: Fragment, exitRoute: Route,
        enterFragment: Fragment, enterRoute: Route
    ) {
        if (exitFragment is ContactListFragment && enterFragment is ChatFragment) {
            exitFragment.exitTransition = Slide(Gravity.LEFT)
            enterFragment.enterTransition = Slide(Gravity.RIGHT)
        }

        if (exitFragment is ChatFragment && enterFragment is ContactListFragment) {
            exitFragment.exitTransition = Slide(Gravity.RIGHT)
            enterFragment.enterTransition = Slide(Gravity.LEFT)
        }
    }
}

After the transition is implemented, just add it to the configuration of the FragmentRouter like seen above!

FragmentRouter { 
    transitions {
        register(LoginToContactListTransition())
    }
}
Issues
  • Can't use objects as destination

    Can't use objects as destination

    The annotation processor fails to generate the serialization methods for object destinations.

    Suppose the following destination:

    @Destination
    object HomeDestination: PodDestination()
    

    Kompass generates the following method:

    fun Kompass.Companion.bundleAsHomeDestination(bundle: Bundle): HomeDestination = HomeDestination()
    

    This calls HomeDestination() but should instead call HomeDestination.

    opened by heinrichreimer 7
  • Failing Build when using AndroidX.

    Failing Build when using AndroidX.

    The annotation processor is failing when using androidX libs. Here's the stacktrace. [kapt] An exception occurred: java.lang.IllegalStateException: elementUtils.getTypeElement(this) must not be null at io.sellmair.kompass.compiler.extension.RenderContextUse$DefaultImpls.asElement(ProcessingEnvironment+use.kt:91) at io.sellmair.kompass.compiler.destination.visitor.AutoMapVisitor.asElement(AutoMapVisitor.kt:13) at io.sellmair.kompass.compiler.extension.RenderContextUse$DefaultImpls.asType(ProcessingEnvironment+use.kt:95) at io.sellmair.kompass.compiler.destination.visitor.AutoMapVisitor.asType(AutoMapVisitor.kt:13) at io.sellmair.kompass.compiler.extension.RenderContextUse$DefaultImpls.asType(ProcessingEnvironment+use.kt:119) at io.sellmair.kompass.compiler.destination.visitor.AutoMapVisitor.asType(AutoMapVisitor.kt:13) at io.sellmair.kompass.compiler.destination.visitor.AutoMapVisitor.destinationCase(AutoMapVisitor.kt:72) at io.sellmair.kompass.compiler.destination.visitor.AutoMapVisitor.destinationCase(AutoMapVisitor.kt:61) at io.sellmair.kompass.compiler.destination.visitor.AutoMapVisitor.buildImplementation(AutoMapVisitor.kt:39) at io.sellmair.kompass.compiler.destination.visitor.AutoMapVisitor.visit(AutoMapVisitor.kt:26) at io.sellmair.kompass.compiler.destination.visitor.AutoMapVisitor.visit(AutoMapVisitor.kt:16) at io.sellmair.kompass.compiler.destination.visitor.AutoMapVisitor.visit(AutoMapVisitor.kt:13) at io.sellmair.kompass.compiler.common.VisitorKt$plus$1.visit(Visitor.kt:10) at io.sellmair.kompass.compiler.common.VisitorKt$plus$1.visit(Visitor.kt:9) at io.sellmair.kompass.compiler.common.VisitorKt$plus$1.visit(Visitor.kt:9) at io.sellmair.kompass.compiler.DestinationProcessor.process(DestinationProcessor.kt:54) at org.jetbrains.kotlin.kapt3.base.ProcessorWrapper.process(annotationProcessing.kt:99) at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:794) at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:705) at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1800(JavacProcessingEnvironment.java:91) at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1035) at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1176) at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170) at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1068) at org.jetbrains.kotlin.kapt3.base.AnnotationProcessingKt.doAnnotationProcessing(annotationProcessing.kt:55) at org.jetbrains.kotlin.kapt3.base.AnnotationProcessingKt.doAnnotationProcessing$default(annotationProcessing.kt:27) at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.runAnnotationProcessing(Kapt3Extension.kt:210) at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:175) at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:93) at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM$analyzeFilesWithJavaIntegration$2.invoke(TopDownAnalyzerFacadeForJVM.kt:98) at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:108) at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:85) at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:370) at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:61) at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:101) at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:361) at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:126) at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:154) at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:51) at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:94) at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:50) at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:88) at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$1$1$2.invoke(CompileServiceImpl.kt:408) at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$1$1$2.invoke(CompileServiceImpl.kt:101) at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:929) at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:101) at org.jetbrains.kotlin.daemon.common.DummyProfiler.withMeasure(PerfUtils.kt:137) at org.jetbrains.kotlin.daemon.CompileServiceImpl.checkedCompile(CompileServiceImpl.kt:969) at org.jetbrains.kotlin.daemon.CompileServiceImpl.doCompile(CompileServiceImpl.kt:928) at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:407) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:346) at sun.rmi.transport.Transport$1.run(Transport.java:200) at sun.rmi.transport.Transport$1.run(Transport.java:197) at java.security.AccessController.doPrivileged(Native Method) at sun.rmi.transport.Transport.serviceCall(Transport.java:196) at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683) at java.security.AccessController.doPrivileged(Native Method) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)

    opened by roshanpisharody 5
  • Keep state on Process-Death

    Keep state on Process-Death

    Kompass doesn't keep the current state on process-death. Routing to a certain destination, terminating the app, re-opening will lead route to the last destination. This could be changed by separating lambdas and destinations from inside the backstack and serializing the backstack to the onSaveInstance bundle.

    0.2.0 feature 
    opened by fablue 4
  • [73] LoginProcessingFragment stuck loading

    [73] LoginProcessingFragment stuck loading

    Fix issue where LoginProcessingFragment gets stuck loading.

    It's actually not required to remove the Handler callback, as this will be handled correctly without the stop method in the case of both configuration change and process death. onCleared already does a perfect job of cleaning these up when they need to be cleaned up!

    opened by isaac-udy 3
  • Question about destination .

    Question about destination .

    Hi , currently im using your library its great and ease to implement and may i know how to identify which is destination is currently is active? or is there a currently function to that please let me know thanks.

    opened by maccam04 3
  • Decouple Android dependencies

    Decouple Android dependencies

    I believe, Kompass is a great router not only for Android. If we decouple the Android-related implementation detail into separate modules, we could use Kompass also for other frameworks. I guess that would have a clear benefit and shouldn't even be too complicated as the only Android-dependent stuff is Bundle and how to set a sail, which of course can be generalized using some clever interfaces and modules.

    Clearly, this would break some code, but I would like to investigate the idea further.

    0.2.0 
    opened by heinrichreimer 3
  • Support For AndroidX

    Support For AndroidX

    There should be another artifact for supporting the androidx namespace.

    opened by roshanpisharody 2
  • Sample: LoginProcessingFragment can get stuck in loading state forever

    Sample: LoginProcessingFragment can get stuck in loading state forever

    https://github.com/sellmair/kompass/blob/ceed98827b5aa5687df78b83d9de8060ffc7e0dc/android-example--fragment/src/main/java/io/sellmair/kompass/android/example/viewmodel/LoginProcessingViewModel.kt#L37-L39

    Because of viewModel.stop() in onPause, if app is put to background and brought to foreground while LoginProcessingFragment is on front, then the app gets stuck here forever.

    You might want to consider some form of observable that the is bound to onStart/onStop rather than onPause (and no counterpart).

    After rotation, it still gets stuck on the screen:

    Screenshot 2019-05-06 at 13 39 37 bug example 
    opened by Zhuinden 2
  • nested destinations

    nested destinations

    Support destinations like

    class OuterDestination {
         @Destination
         class InnerDestination
    }
    
    feature 
    opened by sellmair 2
  • Remove sample unit tests

    Remove sample unit tests

    Remove sample unit tests generated by Android Studio when creating a module.

    opened by heinrichreimer 2
  • Discussion: DSL syntax

    Discussion: DSL syntax

    I'd like to start a bit of a discussion around the DSL syntax.

    Multiple paths to one goal:

    router.clear()
    router.push(Route())
    
    router { 
        clear() push Route()
    }
    
    router {
        clear()
        push(Route())
    }
    

    There are several ways to perform similar actions. The first way isn't correct, as it won't bundle up the actions as a single item, but my understanding is the last two ways are essentially the same. ̛I think it would be a better idea to have a single syntax, even if it means that a single "push" needs to be performed as:

    router { push() }
    

    Builder syntax:

    router {
        clear() push RouteA() push RouteB() push RouteC()
    }
    

    The builder continuation syntax that allows a user to push a series of routes like this is inconsistent with the use of infix functions, as a user is unable to split these onto different lines. The following code will not compile:

    router {
        clear() push RouteA()
            push RouteB()
            push RouteC()
    }
    

    I have two questions:

    1. Is the builder/continuation syntax actually useful? Could commands just be split onto different lines?
    2. If the builder/continuation syntax is useful, should the use of infix be removed, so a user can split the continuation over multple lines?
    opened by isaac-udy 15
  • Core: add JS support

    Core: add JS support

    opened by sellmair 0
  • Direct `FragmentRouteStorage`

    Direct `FragmentRouteStorage`

    It may be possible to implement a FragmentRouteStorage that takes the key of a route and retrieves the router later from the router by using the key again

    opened by sellmair 10
  • Tests for `DefaultFragmentStackPatcher`

    Tests for `DefaultFragmentStackPatcher`

    0.2.0 test 
    opened by sellmair 0
  • Create beginners tutorial

    Create beginners tutorial

    enhancement 
    opened by sellmair 0
  • Create

    Create "getting started"

    enhancement 
    opened by sellmair 0
  • Create nicer / more concise readme

    Create nicer / more concise readme

    enhancement 
    opened by sellmair 0
  • Improve Java API's

    Improve Java API's

    opened by sellmair 0
Releases(v0.2.0-alpha.5)
  • v0.2.0-alpha.5(Aug 28, 2019)

  • v0.2.0-alpha.3(Aug 26, 2019)

    • Upgrade Kotlin to 1.3.50
    • Lower minSdk to 19
    • Android: Declare AndroidX lifecycle extensions as a transitive dependency
    • Android: Declare AndriodX Fragment as a transitive dependency
    Source code(tar.gz)
    Source code(zip)
  • v0.2.0-alpha.1(May 5, 2019)

  • v0.2.0-alpha.0(May 4, 2019)

    First alpha release of version 0.2.x Major changes:

    • Project is now fully migrated to AndroidX
    • Project is now build for multiplatform (JVM, Android, iOS, MacOS)
    • Replaced "funny" naming schema (after a lot of internal criticism at QuickBird Studios)
    • Fully replaced annotation processing (recommendation is @Parcelize) now
    • Fixed a lot of issues with the pre 0.2.x concept (like process death, or configuration changes)

    While this project changed a lot with this 0.2.x release, the migration should be fairly simple. Right now, there is no migration guide available, but I am happy to help anyone over gitter https://gitter.im/kompass-android/Help

    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Apr 14, 2019)

    Changes prior to v0.1.0-beta.0

    The is just a version bump, since the last release (v0.1.0-beta.0) has proven to work reliable in many projects.

    Source code(tar.gz)
    Source code(zip)
  • v0.1.0-beta.0(Nov 6, 2018)

  • v0.1.0-alpha.2(Sep 23, 2018)

  • v0.1.0-alpha.1(Sep 1, 2018)

    Changes prior to 0.1.0-alpha.0

    • Fragments now also have a convenience .sail() method to create a new KompassSail #30
    • Fixed bug when accessing ship for the first time from background thread #34
    Source code(tar.gz)
    Source code(zip)
  • v0.1.0-alpha.0(Aug 21, 2018)

    Changes prior to 0.1.0-pre-alpha.3

    • Added convenience value kompass.main to retrieve a ship "main"
    • Support for constructors with default values #19
    • Support for method accessors #20
    • SUPPORT FOR MULTIPLE CONSTRUCTORS #19
    Source code(tar.gz)
    Source code(zip)
  • v0.1.0-pre-alpha.3(Aug 19, 2018)

    v0.1.0-pre-alpha.3

    This is the first public release of 0.1.0. 0.1.0 is completely written from scratch. Main goals:

    • Refine the API
    • Refine the architecture of the software to support multiple ways of routing
    • Support raw View based routing
    • Create high-quality unit and integration tests for this project

    Changes to 0.0.10

    • popBackImmediate is now backImmediate
    • popBack is now back
    • setSail now returns a KompassReleasable instead of KompassSail
    • setSail expects a KompassSail wich can be retrieved by Activity.sail
    • KompassReleasable can be released by Lifecycle or LifecycleOwner
    • Kompass.builder does not require Context anymore
    • autoPilot is now autoDetour
    • asBundle is now toBundle
    • MISSING SUPPORT for multiple constructors and default params in constructors

    Additional notes

    • Upgrade requires the project to be cleaned
    Source code(tar.gz)
    Source code(zip)
  • v0.0.10(Feb 22, 2018)

  • v0.0.7(Feb 9, 2018)

    closes #10 closes #9

    • Infix/Operator notation/for navigation

      • ship.navigateTo(destination) can be expressed as ship += destination
      • ...
    • Support optional and boxed primitves for autoCrane

    Source code(tar.gz)
    Source code(zip)
  • v0.0.6(Feb 8, 2018)

    Implemented chain based routing

    • navigateTo(destination, replaceCurrent) is now deprecated
    • Three new operators are introduced:
      • startAt(destination)
      • navigateTo(destination)
      • beamTo(destination)
    Source code(tar.gz)
    Source code(zip)
Owner
Sebastian Sellmair
Sebastian Sellmair
Unidirectional Data Flow in Kotlin - Port of https://github.com/ReSwift/ReSwift to Kotlin

ReKotlin Port of ReSwift to Kotlin, which corresponds to ReSwift/4.0.0 Introduction ReKotlin is a Redux-like implementation of the unidirectional data

null 475 Jul 29, 2021
Model-View-ViewModel architecture components for mobile (android & ios) Kotlin Multiplatform development

Mobile Kotlin Model-View-ViewModel architecture components This is a Kotlin Multiplatform library that provides architecture components of Model-View-

IceRock Development 385 Jul 29, 2021
Extendable MVI framework for Kotlin Multiplatform with powerful debugging tools (logging and time travel), inspired by Badoo MVICore library

Should you have any questions or ideas please welcome to the Slack channel: #mvikotlin Inspiration This project is inspired by Badoo MVICore library.

Arkadii Ivanov 614 Aug 1, 2021
Redux implementation for Kotlin (supports multiplatform JVM, native, JS, WASM)

Redux-Kotlin ![badge][badge-ios] A redux standard for Kotlin that supports multiplatform projects. Full documentation at http://reduxkotlin.org. Misso

Redux-Kotlin 186 Jul 27, 2021
MVU for Kotlin Multiplatform

Oolong Oolong is an Elm inspired Model-View-Update (MVU) implementation for Kotlin multiplatform. As the name implies, three core concepts comprise th

Oolong 259 Jul 30, 2021
BaseDemo 是Android MVVM + Retrofit + OkHttp + Coroutine 协程 + 组件化架构的Android应用开发规范化架构

BaseDemo 是Android MVVM + Retrofit + OkHttp + Coroutine 协程 + 组件化架构的Android应用开发规范化架构,通过不断的升级迭代,目前主要分为两个版本,分别为分支 MVVM+Databinding 组件化版本,分支MVVM+Databinding+Single 单体版本。旨在帮助您快速构建属于自己的APP项目架构,做到快速响应上手,另外再长期的实践经验中汇总了大量的使用工具类,主要放在了项目 `lib_common` 组件中,以供大家参考使用。具体使用请开发者工具自己项目需求决定选择如何使用。

Huan Zhou 35 Jul 22, 2021
A sample project in Kotlin to demonstrate AndroidX, MVVM, Coroutines, Hilt, Room, Data Binding, View Binding, Retrofit, Moshi, Leak Canary and Repository pattern.

This repository contains a sample project in Kotlin to demonstrate AndroidX, MVVM, Coroutines, Hilt, Room, Data Binding, View Binding, Retrofit, Moshi, Leak Canary and Repository pattern

Areg Petrosyan 5 May 24, 2021
Moxy is MVP library for Android

Moxy This Moxy repository is deprecated and no longer supported. Please migrate to the actual version of the Moxy framework at Moxy communuty repo. De

Arello Mobile 1.6k Jul 25, 2021
MVVM RECIPE ANDROID APP Is an app where I show how to use MVVM, retrofit, dagger hilt, coroutine, liveData, Kotlin, navigation component, and so on...

MVVM RECIPE ANDROID APP Is an app where I show how to use MVVM, retrofit, dagger hilt, coroutine, liveData, kotlin, navigation component, and so on...

Isaias Cuvula 6 Jul 7, 2021
A full-featured framework that allows building android applications following the principles of Clean Architecture.

EasyMVP A powerful, and very simple MVP library with annotation processing and bytecode weaving. EasyMVP eliminates the boilerplate code for dealing w

null 1.3k Jul 21, 2021
Repository that showcases 3 Android app architectures: "Standard Android", MVP and MVVM. The exact same app is built 3 times following the different patterns.

Archi This repository showcases and compares different architectural patterns that can be used to build Android apps. The exact same sample app is bui

Iván Carballo 3.4k Jul 26, 2021
Nucleus is an Android library, which utilizes the Model-View-Presenter pattern to properly connect background tasks with visual parts of an application.

Nucleus Deprecation notice Nucleus is not under develpment anymore. It turns out that Redux architecture scales way better than MVP/MVI/MVVM/MVxxx and

Konstantin Mikheev 2k Jul 16, 2021
A data-binding Presentation Model(MVVM) framework for the Android platform.

PLEASE NOTE, THIS PROJECT IS NO LONGER BEING MAINTAINED. As personal time contraints, I am currently unable to keep up. Please use official android da

RoboBinding open source 1.3k Jul 14, 2021
Tutorial MVVM Fast Android Networking

MVVM-FAN Tutorial MVVM Fast Android Networking Tutorial Build with Android Studio https://youtu.be/nXX-NQIoGjk Tutorial Build with Step by Step https:

Azhar Rivaldi 3 Jul 15, 2021