Search code examples
javaandroidasynchronouskotlinkotlin-interop

Architecture of own SDK - async method API in Kotlin


We are building a public SDK for our product. It is built with Kotlin and internally we use coroutines. However, we want to publish an API that is usable form JAVA, that's why can't provide suspendable functions as public API.

We are ok, if the usability in Java will be less comfortable than in Kotlin, that's quite expected.

So, for example, we are looking of a return type of the following async method:

class Sdk {
    fun getPlace(): ___
}

Things we have considered:

  1. Using a RX Java as a the interface. We don't like this solutions, Rx is quite complex and we want to add as little as possible of other dependencies. Generally, we would go with returning Single. But, Rx java things we don't want to solve (which thread should be the work done) and Rx don't solve things we would like to solve (if possible), e.g. lifecycle & observer - the things solved in Android architecture components.

  2. Java 8 Future. This seems to be most appropriate but not possible since we need to target older Androids (4.1 at least).

  3. Android architecture LiveData. Returning a LiveData seems to be ok, there is also a observeForever() method that makes it usable in backgrounds threads. On the other hand, the api suggests that it may return repeatadly multiple results. But we want definitely omit only on result or one exception. In Kotlin, though, we may implement extension functions which will make it quite usable as sdk.getPlace().await().

  4. Custom solution: return a simple Result object, you may subsrcibe for the result by providing a callback sdk.getPlace().observe(Observe { onSucccess(data: Place) {} onFailure(e: Throwable) {} }); we will provide an extension function for awaiting.

The questions:

  1. Did we miss some important aspect/library/possibility?
  2. Which solution we should choose and why.

Solution

  • I'm not sure whether this question has a concrete answer. So all the following is just my opinion. You can either agree or disagree. There are a lot of different ways to achieve what the OP asked.

    Personally, I would not include any dependencies on Rx or Architecture Components with LiveData. While a lot of modern apps use these dependencies I do not think it's a good idea to have a lot of 3rd party dependencies in your SDK. Other developers could override them and it could lead to unpredictable results.

    I see 2 solutions:

    1. Ask yourself whether you can make this method non async and let clients figure out how to use them. It might sound not very user-friendly but as developers you know that they will probably end up with their own async wrapper around the SDK callbacks.
    2. Use a custom callback. This is a pretty straightforward and common way to provide a public API in Android world. If other devs use Rx then they know how to wrap these methods to follow their streams. The same is true for LiveData users.

    If I were you I would also think about exposing different API methods for Java/Kotlin users. Kotlin users will thank you for providing a cleaner way, e.g. coroutines, to call the SDK's methods.