Can anyone here explain the Kotlin/Native spinner app project structure in detail? Also the specifics on how different modules work - kotlin

I would like to specifically know how the common module is used by the individual client modules. Which are the truly common parts that is shared by all the clients and the server.
Thank you.

This is easy. I suspect you're talking about Kotlin multiplatform modules.
Consider print and println.
In the common module we can expect a print function:
expect fun print(a: String)
But we don't know how was it implemented, because the common module doesn't know anything about Java's System.out, as well as JavaScript's console.
But the common module can expect such function that prints a String on screen, without providing an implementation.
Since we have print, we can implement println:
fun println(a: String) = print("$a\n")
All codes above are inside the common module.
And all you have to do is to to implement print for JVM/JS spererately.
For JVM:
actual fun print(a: String) = System.out.println(a)
For JS:
actual fun print(a: String) = console.log(a)
(Maybe) For Native:
actual fun print(a: String) = printf(a)
The three code blocks above are inside client modules.
Consider you've designed a data format, you have encoding and decoding code. Those codes are used in your Android device (JVM), your backend server (JVM), your frontend webpage (JS), your native app (Native).
You use Kotlin in all those sub projects but you want to write the encoder/decoder only once. Kotlin multiplatform module solves this probelm.
About the spinner app
It's not using the standard kotlin approach for creating multiplatform project. It's a trick on gradle.
There's a readResources (and randomInit as well, for osx/linux) function that implements differently on platforms but of the same signature, and gradle will decide which Kommon.kt should be compiled with the client projects.
readResources and randomInit should be marked as actual, and there should be a "common module" that has "expect"ed those two functions.
They didn't do this probably because Kotlin 1.2 (which brings stable multiplatform support) isn't out when KotlinConf holds.

Related

How to use Web Speech API in Kotlin Multiplatform for web application

Do you know how to use Web Speech API in KMM project for Web application: https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API/Using_the_Web_Speech_API
I'm using Kotlin to build the web app, and the web app require speech to text feature.
I'm not familiar with this particular WEB API, but here's the general process of wrapping global JS APIs in Kotlin so hopefully you'll be able to correct the odd inconsistencies yourself via trial and error.
Firstly, since the target API is global, there's no need for any meta-information for the compiler about where to source JS code from - it's present in the global context. Therefore, we only need to declare the shape of that global context. Normally that would be a straightforward task as outlined in this article, however there's a caveat here which requires some trickery to make it work on all the browsers:
As mentioned earlier, Chrome currently supports speech recognition with prefixed properties, therefore at the start of our code we include these lines to feed the right objects to Chrome, and any future implementations that might support the features without a prefix:
var SpeechRecognition = window.SpeechRecognition || webkitSpeechRecognition;
var SpeechGrammarList = window.SpeechGrammarList || webkitSpeechGrammarList;
var SpeechRecognitionEvent = window.SpeechRecognitionEvent || >webkitSpeechRecognitionEvent;
But let's ignore that for now since the API shape is consistent across the implementation, and name is the only difference that we'll address later. Two main API entities we need to wrap here are SpeechRecognition and SpeechGrammarList, both being classes. However, to make it easier to bridge the inconsistent names for them later on, in Kotlin it's best to describe their shapes as external interfaces. The process for both is the same, so I'll just outline it for SpeechRecognition.
First, the interface declaration. Here we can already make use from EventTarget declaration in Kotlin/JS stdlib. Note that the name of it does not matter here and will not clash with webkitSpeechRecognition when present since we declare it as an interface and as such we only care about the API shape.
external interface SpeechRecognition: EventTarget {
val grammars: SpeechGrammarList // or dynamic if you don't want to declare nested types
var lang: String
// etc...
}
Once we have the API shape declared, we need to bridge naming inconsistencies and provide a unified way to construct its instances from Kotlin. For that, we'll inject some hacky Kotlin code to act as our constructors.
// We match the function name to the type name here so that from Kotlin consumer's perspective it's indistinguishable from an actual constructor.
fun SpeechRecognition(): SpeechRecognition {
// Using some direct JS code to get an appropriate class reference
val cls = js("window.SpeechRecognition || webkitSpeechRecognition")
// Using the class reference to construct an instance of it and then tell the kotlin compiler to assume it's type
return js("new cls()").unsafeCast<SpeechRecognition>()
}
Hopefully this gives you the general idea of how things tie together. Let me know if something's still not quite clear.

Concurrent Hash Map in Kotlin

Is it possible to implement a concurrent hash map purely in Kotlin (without Java dependency)? I am new to Kotlin and it looks like there is no obvious API available in kotlin.collections.
You can probably convert the source without too many issues. It's freely available, here for example. The concurrency model of Kotlin multiplatform (which I'm guessing is your goal, there's no point in reimplementing it if you only target the JVM) is a bit different than the one Java uses, there are no locks for example. But there's no reason why that would prevent it.
The following resources might also help you with the implementation:
Concurrency in Kotlin/Native
kotlin.native.concurrent package
Replacement for synchronized
Official Kotlin/Native Concurrency tutorial
You can try:
val emitters: ConcurrentMap<String, Any> = ConcurrentHashMap()
// get
val obj: Any = emitters[email]
// put:
emitters[email] = this
// delete
emitters.remove(email)
Such way, u don't need to add any library to your project

How to use BigDecimal in Kotlin Multiplatform?

I followed the tutorial https://kotlinlang.org/docs/tutorials/native/mpp-ios-android.html, then I successfully create the folders of androidmain, iosmain and commonmain.
However when I want to implement the datatype BigDecimal in the commonmain. It won't work. I need the decimal dataype for the currency.
I know that the question is old, but, in case anyone stumbles upon this topic, I made a KigDecimal library that implements BigDecimal and BigInteger for kotlin multiplatform (for jvm and js). The library is distributed completely freely. Therefore, I invite everyone to supplement and expand it, if desired.
On the jvm side, BigDecimal and BigInteger are just the corresponding types from java. And on the js side is used https://www.npmjs.com/package/bigdecimal.
The main repository is located here: https://gitflic.ru/project/mikhaylutsyury/kig-decimal
There is also a mirror on github: https://github.com/YuryMikhailuts/kig-decimal
But the mirror can sometimes lag a little behind the main repository.
There is no support for BigDecimal in the Kotlin common code (yet).
You may have a look at the related thread
https://discuss.kotlinlang.org/t/multiplatform-bigdecimal-implementation/5631
You may create your own implementation for such a class with expect and actual keywords.
https://kotlinlang.org/docs/reference/platform-specific-declarations.html
The idea is as follows:
you declare expect declarations for the BigDecimal type in common code
you use the actual annotations at every platform to supply the platform specific implementation (e.g. JVM's BigDecimal class)

Multi-platform InputStream Alternative in Kotlin?

I’m looking for a multi-platform alternative to input streams. My concrete task is to fetch an encrypted file from a remote server via https and decrypt it on demand.
In Java land I would an implement InputStream which proxies the reads to the input stream from the https library. How can I do the same in kotlin targeting multiple platforms.
I see ktor returns an ByteReadChannel, but I don’t know which functions.
I’m lost and don’t know where to start. Thanks for your help in advance.
If the framework you are using does not provide you with a full-fledged InputStream implementation, the only chance left is to write your own. Much like what the ktor developers did: ByteReadChannel is just an abstraction of "reading bytes from a channel".
This abstraction lives in the common part and allows to write application and business logic around it.
The key to make this work in the context of a Kotlin Multiplatform project is, the actual implementation needs to be provided in the platform specific parts. The JVM specific code of the ktor project actually has an implementation that uses InputStream: InputStream.toByteReadChannel.
You certainly don't have to do it like your example from the ktor project and model everything down from byte channels up to file representations. If you want to leverage Kotlin framework classes, Sequences might be handy. This could look something like this:
// in common
interface FileFetcher {
fun fetch(): Sequence<Byte>
}
expect fun fileFetcher(source: String): FileFetcher
// in jvm
class JvmFileFetcher(val input: java.io.InputStream): FileFetcher {
override fun fetch(): Sequence<Byte> = input.readBytes().asSequence()
}
actual fun fileFetcher(source: String): FileFetcher {
val input = java.net.URL(source).openStream()
return JvmFileFetcher(input)
}
You would define an interface FileFetcher along with a factory function fileFetcher in the common part. By using the expect keyword on the fileFetcher function you need to provide platform-specific implementations for all target platforms you define. Use the FileFetcher interface in the common part to implement your logic (decrypting file contents etc.). See the documentation for Sequence for how to work with it.
Then implement the factory function for all platforms and use the actual keyword on them. You will then need to write platform-specific implementations of FileFetcher. My example shows how a JVM version of the FileFetcher interface.
The example is of course very basic and you probably would not want to do it exactly like this (at least some buffering would be needed, I guess). Also, within the JVM part you could also leverage your favorite networking/HTTP library easily.

What is the purpose of actual keyword in Kotlin

I noticed that some functions for coroutines are marked with actual keyword.
From documentation:
actual denotes a platform-specific implementation in multiplatform
projects
As I understood from documentation actual keyword is used for multiplatform projects and should work in pair with expect keyword.
Something like this:
Common module:
package org.jetbrains.foo
expect class Foo(bar: String) {
fun frob()
}
fun main(args: Array<String>) {
Foo("Hello").frob()
}
Corresponding module:
package org.jetbrains.foo
actual class Foo actual constructor(val bar: String) {
actual fun frob() {
println("Frobbing the $bar")
}
}
That case is clear.
But in package kotlinx.coroutines.experimental I noticed that some functions like launch or withContext are marked as actual but there are no expect functions in package.
So what is the purpose of actual keyword without expect?
The kotlinx.coroutines library actually makes use of multiplatform projects since it supports both the JVM and JS compilation targets.
You can find the common module here, and the specific expect declarations for the functions you've mentioned here.
While the source code in the other answer helped, I found this page (linked off of the page #jim-andreas mentioned in the comments above) was much more helpful.
Specifically, this passage:
If you're developing a multiplatform application that needs to access platform-specific APIs that implement the required functionality (for example, generating a UUID), use the Kotlin mechanism of expected and actual declarations.
With this mechanism, a common source set defines an expected
declaration, and platform source sets must provide the actual
declaration that corresponds to the expected declaration. This works
for most Kotlin declarations, such as functions, classes, interfaces,
enumerations, properties, and annotations.
The compiler ensures that every declaration marked with the expect keyword in the common module has the corresponding declarations marked with the actual keyword in all platform modules. The IDE provides tools that help you create the missing actual declarations.
Again, for more information, you can visit this page.