An aar file has a kotlin class like
package com.material.utils;
object Utils {
fun init() {
System.loadLibrary("utils-jni")
}
}
How to call this Utils.init() from a java project that uses this kotlin aar?
You call it like this
Utils.INSTANCE.init();
Related
I'm implementing a library using KMM(Kotlin Multiplatform). And to create an instance of a class I used a static method. However, a static method's not accessible in iOS project. How can I implement it cleanly.
expect class Verifier{
companion object{
fun getInstance():Verifier
}
}
// actual implementations
actual class Verifier{
actual companion object{
actual fun getInstance():Verifier{
/// make an instance and return
}
}
}
And I would like to get an instance of Verifier class as the following:
// calling in swift
Verifier.getInstance()
// calling in kotlin
Verifier.getInstance()
Is it possible to access as above and implement static methods in a shared module.
Thank you!
I'm trying to verify that a method is called with a given argument. That argument is a non-nullable enum type. So I get the exception eq(SomeEnum.foo) must not be null. Here is a sample what I'm trying to do:
enum class SomeEnum {
foo, bar
}
open class MyClass {
fun doSomething() {
magic(SomeEnum.foo)
}
internal fun magic(whatever: SomeEnum) {}
}
#Test
fun mockitoBug() {
val sut = spy(MyClass())
sut.doSomething()
verify(sut).magic(eq(SomeEnum.foo))
}
Capturing does not work too. What can I do or is that really a bug as I assume?
Because Mockito was designed for Java, it doesn't play well with Kotlin's null checks. A good solution is to use the mockito-kotlin extensions library: https://github.com/mockito/mockito-kotlin
It includes Kotlin versions of the matchers that won't return null. Add a dependency on mockito-kotlin and just make sure to import the Kotlin versions instead of the Java ones.
Currently, I'm creating a function, which is available for the dependencies block in Groovy with:
project.dependencies.ext.foo = { String value ->
project.files(extension.getFooDependency(project).jarFiles).asFileTree
}
Thanks to that, I'm able to do:
afterEvaluate {
dependencies {
compileOnly foo('junit')
}
}
I'm converting the Groovy code to Kotlin, and I'm wondering how to rewrite this foo extension.
I've ended up with:
project.dependencies.extensions.extraProperties.set("foo", Action { value: String ->
project.files(extension.getIdeaDependency(project).jarFiles).asFileTree
})
After calling foo('junit'), I get the following exception:
> Could not find method foo() for arguments [junit] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
I do not think that would work the same way in Kotlin DSL. Instead, you may declare a Kotlin extension function somewhere in the project. Then calling it would include all necessary receivers to you.
For multiple projects, I would recommend using a buildSrc project. Declarations there are visible to all project files below.
Speaking about Groovy and Kotlin support, I would do something like that:
private fun getFooImpl(scope: getFooImpl, name: String) { /*here is the implementation */ }
fun DependencyHandlerScope.getFoo(name:String) = getFooImpl(this, name)
//in Groovy
project.dependencies.extensions.extraProperties.set("foo", {getFooImpl(..)})
The same code could fit into a plugin as well. A more generic way could be to register a custom DLS extension, so to allow a custom block-like thisIsMyPlugin { .. } in the Gradle DSL and define all necessary helper functions in the extension class. Here the downside is in forcing users to wrap their code into the thisIsMyPlugin block.
In Kotlin, a common use for object is using it for singletons, like:
object MyObject {
...
}
However, when using micronaut framework, the official documentation recommends using something like this:
#Singleton
class V8Engine : Engine {
override var cylinders = 8
override fun start(): String {
return "Starting V8"
}
}
Why can't I use simply object instead of using annotation #Singleton with a class?
With a #Singleton, Micronaut can automatically manage dependencies between beans. If you go with the other class in https://docs.micronaut.io/latest/guide/ioc.html#beans, translated to Kotlin:
#Singleton
class Vehicle(private val engine: Engine) {
public fun start() = engine.start()
}
It can't be just an object because takes a parameter.
This parameter is discovered by Micronaut to be the singleton instance of V8Engine, which needs that to be a #Singleton and not an object.
Of course, in this case you could just directly use V8Engine in Vehicle; but it's easier to change e.g. if you want Engine not to be a singleton anymore.
Why can't I use simply object instead of using annotation #Singleton
with a class?
You can use object instead of using #Singleton with a class. Micronaut won't manage instances for you, but that is allowed.
I'm trying to follow this tutorial https://dev.to/tagmg/step-by-step-guide-to-building-web-api-with-kotlin-and-dropwizard and am instead writing my gradle.build file in Kotlin's DSL and am finding there is no direct mapping from Groovy to Kotlin and I'm now getting this error when running ./gradlew run:
(4, 1): Duplicate JVM class name 'dropwizard/tut/AppKt' generated from: package-fragment dropwizard.tut, package-fragment dropwizard.tut
plugins {
// Apply the Kotlin JVM plugin to add support for Kotlin on the JVM.
id("org.jetbrains.kotlin.jvm").version("1.3.31")
// Apply the application plugin to add support for building a CLI application.
application
}
repositories {
// Use jcenter for resolving dependencies.
// You can declare any Maven/Ivy/file repository here.
mavenCentral()
jcenter()
}
dependencies {
// Use the Kotlin JDK 8 standard library.
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
// Use the Kotlin test library.
testImplementation("org.jetbrains.kotlin:kotlin-test")
// Use the Kotlin JUnit integration.
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
compile("io.dropwizard:dropwizard-core:1.3.14")
}
application {
// Define the main class for the application
mainClassName = "dropwizard.tut.AppKt"
}
tasks.withType<Jar> {
manifest {
attributes["Main-Class"] = application.mainClassName
}
from({
configurations.runtimeClasspath.get().filter { it.name.endsWith("jar") }.map { zipTree(it) }
})
}
tasks.named<JavaExec>("run") {
args("server", "config/local.yaml")
}
I cannot tell (yet) why this happens but to work around it add #file:JvmName("SomethingUnique") to your JVM file. Note that renaming the file will not help and lead to the same error. Only changing the output name will resolve it.
The JVM only knows how to load classes, so the Kotlin-to-JVM compiler generates classes to hold top-level val or fun declarations.
When you have two similarly named files
// src/commonMain/kotlin/com/example/Foo.kt
package com.example
val a = 1
and
// src/jvmMain/kotlin/com/example/Foo.kt
package com.example
val b = 2
the kotlin-to-JVM compiler generates
package com.example;
public class FooKt {
public static final int a = 1;
}
and
public com.example;
public class FooKt {
public static final int b = 2;
}
Obviously, these two files can't coexist in the same JVM ClassLoader, hence the error message.
Solutions involve:
As #Fleshgrinder noted, adding a file-level JvmName annotation to at least one to override the derived name, FooKt.
Renaming files to be different where possible.
Moving top-level val and fun declarations from those files into other files so Kotlin does not need to create the FooKt class.
Moving top-level val and fun declarations into objects or companion objects.