15

I'm new to Android development (started 6 months ago) and would like to move from Java to Kotlin. I've converted my project to Kotlin and fixed all issues but one and I can't figure out how to fix it.

I'm attempting to retrieve a JSONArray (as seen in class JsonManager) and use the retrieved data in a second class called DataDisplayPage via a method call.

I am getting the following console errors, which occur at this line of the second class: jManager.fetch_data{ theJsonArray ->.

Cannot infer a type for this parameter. Please specify it explicitly.

Type mismatch: inferred type is (???) -> Unit but OnTaskCompleted was expected

First class JsonManager

interface OnTaskCompleted {
    fun onTaskCompleted(theJsonArray: JSONArray)
}

class JsonManager {
    var listener: OnTaskCompleted? = null

    init {
        Log.d("JsonManager", "Instance created")
    }

    fun fetch_data(callback : OnTaskCompleted) {
        listener = callback
         val url ="https://someURL"

        AndroidNetworking.get(url)
            .build()
            .getAsJSONArray(object : JSONArrayRequestListener {
                override fun onResponse(response: JSONArray) {
                    listener?.onTaskCompleted(response)
                }

                override fun onError(anError: ANError) {
                    Log.d("error", anError.toString())
                }
            })

}

Second class DataDisplayPage

class DataDisplayPage : AppCompatActivity()

    fun onStartUp() {

        val jManager = JsonManager()

        jManager.fetch_data{ theJsonArray  ->
            val newData = DepData()
            newData.setCellData(theJsonArray as JSONArray)
        }
    }
}

1 Answer 1

17

As of now, you can't use SAM conversion for interfaces defined in Kotlin. There are a couple things you can do to solve your problem though.

  1. If you define your interface in Java, SAM conversion will start working, and your current code will work without any other changes.

  2. If you want to use an interface as the parameter of the fetch_data method, and you want it to be written in Kotlin, you'll have to pass in an object that implements it, which is a slightly verbose, Java-like solution:

    jmManager.fetch_data(object: OnTaskCompleted {
        override fun onTaskCompleted(theJsonArray: JSONArray) {
            // ...
        }
    })
    
  3. If you want a nice pure Kotlin solution, just get rid of the interface, and have the fetch_data function take a function as its parameter instead of the interface (again, your current code in DataDisplayPage will work with this):

    fun fetch_data(callback: (JSONArray) -> Unit) { 
        // ...
        listener?.onTaskCompleted(response)
        callback(response)
        // ...
    }
    

Sign up to request clarification or add additional context in comments.

5 Comments

TIL: you can use the SO subset of HTML inside the code blocks. 👍
I had to look it up just now too :P Also, it only works if you do <pre><code> instead of indentation.
Thank you, this helped me out tremendously. I went with recommendation #2, and will read up a lot more Kotlin documentation to eventually go pure Kotlin.
The third one solution is called higher-order function. It is function that can use other function as argument. It is documented here: kotlinlang.org/docs/reference/lambdas.html I think it is important to read official documentation.
I am moving from Java to Kotlin, and it already feels brilliant. I always hated to define a Java Interface just to be able to pass a "custom" callback to a function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.