How to properly handle generic types? - kotlin

I am trying to create a custom function that will handles all my API response, but I don't know how to properly handle it.
This is my code
My Custom callback
interface ResponseCallback<T> {
fun onSuccess(response: T)
fun onError(code: Int, message: String)
}
This is how I call my request API
createRequest(getLogin(id), object : API.ResponseCallback<LoginResponse>{
override fun onError(code: Int, message: String) {
}
override fun onSuccess(response: LoginResponse) {
}
})
and This is how I handle my request
fun createRequest(source: Observable<*>, callback: ResponseCallback<*>) {
disposable.add(
source.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ it ->
//
// callback.onSuccess(it)
},
{
}
)
)
}
but my problem here is, the callback.onSuccess() parameter is Nothing and can't accept the callback.onSuccess(it)
Please help me, Thanks.

You should only use star projections if you don't know the specific type parameter for a generic type. When you use these, the compiler will prevent you from doing unsafe things with the parameterized type. For example, you've seen that you can't pass in any parameter to onSuccess, since you've essentially told the compiler that you don't know what its type should be.
The fix then is to give your createRequest function a type parameter instead, and make both the Observable be of that type, as well as the callback that you wish to invoke:
fun <T> createRequest(source: Observable<T>, callback: ResponseCallback<T>) {
...
callback.onSuccess(it) // works, since you're passing in a T to a method that requires a T
...
}

Related

How to call constructor default lambda using Kotlin Refelction?

Trying to call lambda provided by MyClass constructor using Kotlin Reflection.
data class MyClass(
var magic:Int=2,
var lambdaValue: ()->String = { //trying to call this lambda from reflection
"Working"
},
)
fun main(args: Array<String>) {
val clazz=MyClass::class
val obj=clazz.createInstance()
val kProperty=clazz.memberProperties
clazz.constructors.forEach{cons-> // for each construtor
cons.parameters.forEach{ parameter-> // looping through constructor parameters
val property=kProperty.find { it.name==parameter.name } // finding the exact property
print(parameter.name+" : ")
if(parameter.type.arguments.isEmpty()) // if empty Int,Float
{
println(property?.get(obj))
}else{
println(property?.call(obj)) // unable to call lambda
}
}
}
}
property.call(obj) returns Any which is not invokable. Any solution?
Expected:
magic : 2
lambdaValue : Working
Frankly speaking, I'm not sure what was your idea behind parameter.type.arguments.isEmpty(). It seems unrelated to what you try to do.
If we have a value of the property already, we can simply check its type and if its is a function then invoke it:
val value = kProperty.find { it.name==parameter.name }!!.get(obj)
print(parameter.name+" : ")
when (value) {
is Function0<*> -> println(value())
else -> println(value)
}
I think usefulness of such a code in generic case isn't very high. This code doesn't know what is the function and if it is going to return a value or perform some action, etc. Maybe in your specific case it is more useful.

Kotlin custom Scope function return type not behaving as expected

this custom function call's a lambda block when null.
I expected the function definition below to enforce the same return type. : T
Is their a way to enforce that be block returns type T ?
inline fun <T> T?.whenNull(block: () -> T): T {
if (this == null) {
return block() //accepts any return type
} else {
return this
}
}
fun main() {
val x : Int? = null
println(x ?: 42)
println(x.whenNull { 42 })
println(x.whenNull { "why is kotlin not enforcing return of the same type?" })
}
T in the second whenAll call is being inferred as Any. Imagine that all occurrences of T are replaced Any, the call would be valid, wouldn't you agree? Int and String are both subtypes of Any, after all.
inline fun Any?.whenNull(block: () -> Any): Any {
if (this == null) {
return block()
} else {
return this
}
}
fun main() {
println(x.whenNull { "why is kotlin not enforcing return of the same type?" })
}
Basically, the Kotlin compiler is "trying too hard" here to make your code compile, and infers an unexpected type for your type parameter.
There exists an internal annotation #kotlin.internal.InputTypesOnly that would prevent your code from compiling if the type inferred is not mentioned in one of the input types (parameter types, receiver type, etc) of the function.
In this case, the input type is just Int?, and T is inferred to be Any, so it would be make your code not compile as expected. Unfortunately though, this annotation is internal, and you cannot use it :( KT-13198 is the ticket about making it public.
Interestingly, when passing this to the block the type is preserved and works as expected.
inline fun <T> T?.whenNullAlt(block: (T?) -> T): T {
if (this == null) {
return block(this) // "this" is superfluous, but enforces same return type
} else {
return this
}
}
fun main() {
val x : Int? = null
println(x.whenNullAlt { 42 })
println(x.whenNullAlt { "does not compile" })
}
As other answers pointed out, this is technically correct from Kotlin viewpoint because it can infer T to Any and it would compile.
However, while technically correct, this is a known problem in Kotlin language and is going to be fixed some day. That noted, let's try to understand why your answers's code works while your questions' doesn't.
The reason for this is that lambdas are always inferred last: imagine it as being a queue on what parts of the expression need to have their types inferred and anything inside a lambda is always at the end of the queue, no matter where the lambda is in the expression. So, when going over your example, it infers everything else, decides that the type of this should be Int?, than goes to the lambda, sees a String return type and merges them into Any being very proud of itself.
In the other example, however, the lambda is passed an external fact about it's parameter — the already inferred Int from the receiver (lambda is always the last to get the info, remember?). That way the inference inside the lambda fails because the argument and the result type are in disagreement.

Kotlin - Can you specify return type explicitly on a lambda?

I have an interface
private interface WithTokenExecutor<T> {
fun execute(token: Token): Single<T>
}
and a function withToken that asynchronously gets an access token then returns the executed WithTokenExecutor parameter with the new token.
private fun <T> withToken(executor: WithTokenExecutor<T>): Single<T> {
return essentialApiTokenProvider.getTokenObservable(true) // returns an observable with the token
.flatMap { token -> executor.execute(token)) }
}
Then I to call the function with the:
fun getAppData(apps: List<String>): Single<AppsList> {
return withToken(object : WithTokenExecutor<AppsList> {
override fun execute(token: Token): Single<AppsList> {
return api.getDetails(token) // retuns a Single<AppsList>
}
})
}
This works, so my question is is it possible to change the return statement from an anonymous class to lambda even if the return type of the withToken and the WithTokenExecutor functions are generic?
I have tried doing this:
return withToken({ token -> api.getDetails(token) })
but the compiler says:
Type inference failed: fun <T> withToken(executor: StoreManager.WithTokenExecutor<T>):Single<T> cannot be applied to ((???) -> Single<AppsList>)
Is there a way to explicitly define the return type of these functions while still keeping the lambda?
If you have the option of modifying your declaration of WithTokenExecutor to:
typealias WithTokenExecutor<T> = (t : Token) -> Single<T>
...you will be able to implement your getAppData like this:
fun getAppData(apps: List<String>): Single<AppsList> = withToken { api.getDetails(it) }
If changing the declaration is not possible, it seems like you are out of luck until Kotlin 1.4 as #Pawel points mentions in the comments.

How to call a lambda callback with mockk

I create a mock of a class with mockk.
On this mock I now call a method that gets a lambda as a parameter.
This lambda serves as a callback to deliver state changes of the callback to the caller of the method.
class ObjectToMock() {
fun methodToCall(someValue: String?, observer: (State) -> Unit) {
...
}
}
How do I configure the mock to call the passed lambda?
You can use answers:
val otm: ObjectToMock = mockk()
every { otm.methodToCall(any(), any())} answers {
secondArg<(String) -> Unit>().invoke("anything")
}
otm.methodToCall("bla"){
println("invoked with $it") //invoked with anything
}
Within the answers scope you can access firstArg, secondArg etc and get it in the expected type by providing it as a generic argument. Note that I explicitly used invoke here to make it more readable, it may also be omitted.
I had to look for a bit more example for the callback and found some example in Kotlin Test with Mockk. In my case, it's a bit more specific.
I wanted to check and mock the onFailure and onSuccess case of a a custom callback implementation MyCustomCallback implementing the ListenableFutureCallback.
The code would look like that for my ExampleProducer class that would have a send function:
fun send(data: String) {
val responseFuture = kafkaTemplate.send(topic, data)
responseFuture.addCallback(MyCustomCallback())
}
So here who would the test go:
#Test
fun onFailureTest() {
kafkaTemplate: KafkaTemplate<String, String> = mockk()
val captureCallback = slot<ListenableFutureCallback<SendResult<String, String>>>()
every { callback.addCallback(capture(captureCallback)) } answers {
captureCallback.captured.onFailure(Throwable())
}
every { kafkaTemplate.send(any()) } returns callback
val prod: ExampleProducer = ExampleProducer()
prod.send("test")
// Then you can verify behaviour or check your captureCallback.captured
verify { kafkaTemplate.send(any()) }
assertNotNull(captureCallback.captured)
}
Maybe not exactly what you ask about, but you can use the funciton type for the mock:
val observerMock = mockk<(State) -> Unit>()

How to understand this snippet of Kotlin code?

I come from Java and I'm following a tutorial online regarding using the Volley library to make web requests in Android.
The instructor created the request variable like this:
val registerRequest = object : StringRequest(Method.POST, URL_REGISTER, Response.Listener {
println(it) // will print the response
complete(true)
}, Response.ErrorListener {
Log.d("ERROR", "Could not register user: $it")
complete(false)
}) {
override fun getBodyContentType(): String {
return "application/json; charset=utf-8"
}
override fun getBody(): ByteArray {
return requestBody.toByteArray()
}
}
I understand that he's creating a registerRequest variable of type StringRequest. But what I don't understand is why he prefixed StringRequest with object : here.
Also I understand that StringRequest constructor takes in an Int, String, Lambda, Lambda. After that it becomes confusing to me because the developer was able to declare some override methods after the constructor closes. Why did they do this? From what I can tell, this is similar to subclassing StringRequest, then writing the override methods there? Am I right?
Coming from Java, this way of writing code is quite unusual to me.