Kotlin在这里新学,并尝试学习使用高阶函数和传递lambda的最佳方法。我已创建此方法来调用API并返回从字符串创建的对象,如果出现错误则返回失败。
fun getDeviceStatus(onSuccess: (Device) -> Unit, onFailure: ((String) -> Unit)? = null) {
FuelClient.get(DEVICE_URL,
success = { responseString ->
val adapter = MoshiUtil.moshi.adapter(Device::class.java)
val deivce= adapter.fromJson(responseString)!!
onSuccess(device)
},
failure = { onFailure?.invoke(it.message!!)})
}
我可以像这样使用这个功能:
DeviceService.getDeviceStatus(
{ w ->
print("device")
},
{ e -> print(e) })
但令我烦恼的是,我无法看到函数的名称,看看每个函数的作用。我想知道是否有更清洁/更好的方法来做到这一点,比如
DeviceService.getDeviceStatus(){
onSuccess{print("device")}
onFailure{print("error")}
}
或者
DeviceService.getDeviceStatus()
.onSuccess{print("device")}
.onFailure{print("error")}
但那些错误。有关如何最好地处理onSuccess / onFailure用例的任何想法很常见吗? THX
答案 0 :(得分:0)
对于这种特定情况,当第二个lambda是可选的时,infix
函数可以很好地工作:
sealed class DeviceStatusResult {
abstract infix fun onFailure(handler: (String) -> Unit)
}
class DeviceStatusSuccess(val device: Device) : DeviceStatusResult() {
override fun onFailure(handler: (String) -> Unit) = Unit
}
class DeviceStatusFailure(val errorMessage: String) : DeviceStatusResult() {
override fun onFailure(handler: (String) -> Unit) = handler(errorMessage)
}
fun getDeviceStatus(onSuccess: (Device) -> Unit): DeviceStatusResult {
// get device status
// if (success)
val device = Device()
onSuccess(device)
return DeviceStatusSuccess(device)
// else
// return DeviceStatusFailure(message)
}
然后可以像
一样使用getDeviceStatus { device ->
println(device)
} onFailure { errorMessage ->
System.err.println(errorMessage)
}
也许onFailure
应该叫orFail
或类似的名称。
第二个参数为可选时,这是很好的选择,但不是那么多,因为它不会强迫用户实际提供故障处理程序。而且我认为这不是一个好主意,因为它很容易意外地忽略故障处理程序。最好强迫用户提供一个,即使它恰好是一个空的。因此,在这种情况下,最好使用命名参数,即使没有强制要求实际命名它们的情况。
答案 1 :(得分:0)
例如我们有一个类需要有多个函数,例如两个函数作为参数:
class TestClass internal constructor(
private val onClickShowName: (String) -> Unit,
private val onClickShowSurname: (String) -> Unit
) { //Your work. }
然后你需要创建 val 作为 TestClass:
class MainActivity {
val mTestClass = TestClass(
onClickShowName = {dataText: String -> Log.i("CANER", dataText)},
onClickShowSurname = {dataText: String -> Log.i("CANER", dataText)}
)
}