Rx Kotlin: map function can't infer return type
Asked Answered
B

2

12

In an app that connects to bluetooth devices, I am using the following function using RxKotlin:

private fun startBluetoothPair(device: BluetoothDevice) {
    Observable.just(device)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .map {
            var uuid: UUID = BLUETOOTH_UUID
            var socket = it.createRfcommSocketToServiceRecord(uuid)
            socket.connect()
            return socket
        }
        .subscribe {
            // Do something with the BluetoothSocket
        }
}

This function should simply connect with the bluetoothdevice on the background and then do something with the socket (in the mainthread again). However, the map can't handle the return socket part, telling me there is a Type mismatch, it found a BluetoothSocket where it required a Unit.

What is going wrong here? I thought a map should be able to infer the return type.

Baht answered 5/5, 2017 at 14:4 Comment(3)
Have you tried return@scan instead of return?Nicoline
@Rehan: Thank you, that works! (Or at least, it doesn't complain anymore, can't test right now) But to me, scan looks like pure magic.. What does this do? Care to elaborate?Baht
It is used to avoid ambiguities and return values in nested functions like your case above. I have seen android studio suggesting it more since I updated kotlin plugin last week. You can read more details here and here :)Nicoline
N
36

In your map function replace the statement

return socket

with

return@map socket

Because return statement is normally used to return values for top-level functions. For lambda expressions and inline (nested) functions, use returns at labels i.e. return@{method_name}. You can also leave last line just to socket in the case, and the compiler will handle it for you assuming the last line as return value for the inline function. But for better readability, I will definitely prefer qualified return syntax. You can read more details in kotlin documentation here and here

Nicoline answered 5/5, 2017 at 14:43 Comment(2)
Thank you buddy <3Wheelsman
Thank you! I was going mad trying to get Kotlin map to do what I need it to do. Why not do like other languages have already been doing?Genista
B
2

Just simply skip using the return keyword in this case! The last statement will be the return expression:

.map {
  val uuid: UUID = BLUETOOTH_UUID
  val socket = it.createRfcommSocketToServiceRecord(uuid)
  socket.connect()
  socket
}

It's recommended to avoid using labeled expressions like return@map, because of the maintainability and less complexity.

It's also a good practice using val instead of var for these variables since you don't reassign them.

Borrero answered 3/2, 2021 at 6:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.