Как я могу использовать здесь лямбда-выражение? - PullRequest
1 голос
/ 30 мая 2020

У меня есть собственный класс GetVolley

class GetVolley(private val mContext: Context, private val url: String, private val onVolleySuccess: OnVolleySuccess?, private val mOnVolleyError: OnVolleyError?, private val mOnVolleyEnd: OnVolleyEnd?) {
    private fun getDataVolley() {
        Log.d("GetVolleyUrl", url)
        val request = JsonObjectRequest(Request.Method.GET, url, null, Response.Listener { response: JSONObject ->
            Log.d("GetVolleyResult", response.toString())
            if (response.has("result") && response.getBoolean("result")) {
                onVolleySuccess?.onSuccess(response)
            } else if (response.has("message")) {
                if (mOnVolleyError != null) mOnVolleyError.onError(response.getString("message"))
                else Toast.makeText(mContext, response.getString("message"), Toast.LENGTH_LONG).show()
            }
            mOnVolleyEnd?.onEnd()
        }, Response.ErrorListener { volleyError: VolleyError ->
            Log.d("GetVolleyError", volleyError.message.toString())
            val errorMessage: String = if (volleyError is NetworkError || volleyError is AuthFailureError) {
                "No Internet…"
            } else {
                "Undefinded error"
            }
            if (mOnVolleyError != null) mOnVolleyError.onError(errorMessage)
            else Toast.makeText(mContext, errorMessage, Toast.LENGTH_LONG).show()
            mOnVolleyEnd?.onEnd()
        })
        Volley.newRequestQueue(mContext).add(request)
    }

    init {
        getDataVolley()
    }
}

Интерфейсы в разных файлах:

interface OnVolleySuccess {
    fun onSuccess(response: JSONObject)
}
______________________________________
interface OnVolleyError {
    fun onError(error: String)
}
______________________________________
interface OnVolleyEnd {
    fun onEnd()
}

Когда я использую свой собственный запрос GetVolley. Мой код выглядит так:

GetVolley(this, url, object : OnVolleySuccess {
    override fun onSuccess(response: JSONObject) {
        parseResponse(response)
    }
}, object : OnVolleyError {
    override fun onError(error: String) {
        showError(error)
    }
}, null)

Я хочу, чтобы он выглядел так:

GetVolley(this, url, response -> {
    parseResponse(response)
}, error -> {
    showError(error)
}, null)

Все мои обратные вызовы допускают значение NULL, поэтому я могу установить значение NULL onVolleySuccess, onVolleyError, onVolleyEnd.

Ответы [ 2 ]

2 голосов
/ 30 мая 2020

То, что вы называете преобразования SAM (одиночный абстрактный метод). Он доступен только для интерфейсов Java, но будет доступен для интерфейса Kotlin начиная с Kotlin 1.4. (см. эту статью ). Теперь, если вам нужны лямбды, используйте лямбды:

class GetVolley(
    private val mContext: Context, 
    private val url: String, 
    private val onVolleySuccess: ((response: JSONObject) -> Unit)?, 
    private val mOnVolleyError: ((error: String) -> Unit)?, 
    private val mOnVolleyEnd: (() -> Unit)?
) {

И вместо этого:

onVolleySuccess?.onSuccess(response)

Вы делаете:

onVolleySuccess?.invoke(response)
1 голос
/ 30 мая 2020

Примечание: используйте решение Nicolas, если хотите, поскольку оно изначально использует лямбда, если вы не хотите использовать эти классы в Java

преобразовании SAM, т.е. интерфейсы для обратных вызовов преобразование с использованием лямбда доступно только с версии Kotlin 1.4, которая входит в EAP (Программа раннего доступа).

Если у вас есть Kotlin 1.4-M1 , которые в настоящее время выпускаются, месяцев a go, вы можете объявить свой интерфейс с помощью ключевого слова fun, которое сделает его доступным для использования в качестве лямбда.

fun interface OnVolleySuccess {
    fun onSuccess(response: JSONObject)
}
fun interface OnVolleyError {
    fun onError(error: String)
}
fun interface OnVolleyEnd {
    fun onEnd()
}

Теперь вы можете использовать его следующим образом:

GetVolley(this, url, { response ->
    parseResponse(response)
}, { error ->
    showError(error)
}, null)

// or simply
GetVolley(this, url, { parseResponse(it) }, { showError(it) }, null)

Если у вас возникли трудности с внедрением Kotlin 1.4, вот загвоздка:

// add/change these in build.gradle:
plugins {
    id 'org.jetbrains.kotlin.jvm' version '1.4-M1'
    // ...
}

repositories {
    // ...
    maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
}

// add these in settings.gradle
pluginManagement {
    repositories {
        mavenCentral()
        maven { "https://dl.bintray.com/kotlin/kotlin-eap" }
        maven { "https://plugins.gradle.org/m2/" }
    }
}
...