所以我一直在尝试编写我的第一个 Kotlin Android 库。它是一个包装器,(理论上)应该使使用网络系统发现更容易一些。回顾正在发生的事情以及我正在尝试做的事情。我将抽象大部分代码并将其省略。所以androids内置的NSD在实际使用之前需要大量的样板代码和监听器来实现。我尝试使用现代方法并利用 Kotlins 功能来解决这个问题。所以现在我有一个 NsdHelper 类,您创建一次并使用它来注册、取消注册、发现服务等。这是通过对listers 进行包装来实现的,这些listers 调用helper 类中的特定方法。
辅助方法示例
sName: String,
sType: String,
sPort: Int,
success: (NsdServiceInfo?) -> Unit,
failure: (Exception?) -> Unit
) {
val serviceInfo = NsdServiceInfo().apply {
serviceName = sName
serviceType = sType
port = sPort
}
registerSuccessCallBack = success
registerFailureCallBack = failure
mNsdManager.registerService(
serviceInfo,
NsdManager.PROTOCOL_DNS_SD,
registrationListener
)
}
要注册服务,您需要传递所有必要的信息以及将在失败或成功的情况下执行的 lambda。问题出现在这里,因为我必须在类中存储回调registerSuccessCallBack和registerFailureCallBack。所以看起来像这样
typealias Success = (NsdServiceInfo?) -> Unit
typealias Failure = (java.lang.Exception) -> Unit
// SHOULD BE PRIVATE
var registerSuccessCallBack: Success? = null
var registerFailureCallBack: Failure? = null
正如我自己评论的那样,它们应该是私有的,并且用户不应该可以访问它们,但是我不能像这样实现监听器的方式那样简单地将它们设为私有
class NsdKRegistrationListener(val nsdKelper: NsdKelper) : NsdManager.RegistrationListener{
companion object {
private const val ERROR_SOURCE = "android.net.nsd.NsdHelper.RegistrationListener"
}
override fun onUnregistrationFailed(serviceInfo: NsdServiceInfo?, errorCode: Int) {
Log.d("TAG", "UnRegistration failed $errorCode")
nsdKelper.unRegisterFailureCallBack?.invoke(UnRegistrationFailedException(errorCode.toString()))
}
override fun onServiceUnregistered(serviceInfo: NsdServiceInfo?) {
Log.d("TAG", "Unregistered service $serviceInfo")
nsdKelper.unRegisterSuccessCallBack?.invoke(serviceInfo)
}
所以它们必须是公开的才能被听众访问。我想到了 2 种解决方案,但在网上找不到任何有关如何正确处理此问题的信息。首先是让 Listeners 成为内部类,但这会大大增加 Helper 类的大小,而且感觉不对。另一种解决方案是在函数调用中创建侦听器并将回调传递给它们的构造函数。如果有人有想法,我会非常感谢一些关于如何正确编写以及为什么这样的建议或提示。这是我下定决心要做的最具挑战性的事情之一。