要使用此解决方案,您必须熟悉这些基础知识
- MVVM 架构
- Kotlin 流程(反应式编程)
首先,创建一个密封的数据类来处理套接字事件:
sealed class SocketEvent {
object OpenEvent : SocketEvent()
data class CloseEvent(val code: Int, val reason: String) : SocketEvent()
data class Error(val error: Throwable) : SocketEvent()
data class StringMessage(val content: String) : SocketEvent()
}
其次,您必须创建一个视图模型类来保存 Web 套接字对象,如下所示:
class SocketViewModel : ViewModel() {
private lateinit var client: OkHttpClient
private lateinit var socket: WebSocket
private fun attachWebSocketListener(webListener: WebSocketListener) {
client = OkHttpClient()
val request = Request.Builder().url("http://195.201.167.116:9502").build()
socket = client.newWebSocket(request, webListener)
}
suspend fun socketEventsFlow(): Flow<SocketEvent?> = callbackFlow {
Timber.tag("soxum").d("opening socket")
val socketListener = object : WebSocketListener() {
override fun onMessage(webSocket: WebSocket, text: String) {
trySendBlocking(SocketEvent.StringMessage(text))
}
override fun onOpen(webSocket: WebSocket, response: Response) {
trySendBlocking(SocketEvent.OpenEvent)
}
override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
trySendBlocking(SocketEvent.CloseEvent(code, reason))
}
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
trySendBlocking(SocketEvent.Error(t))
cancel("", t)
}
}
attachWebSocketListener(socketListener)
awaitClose { socket.cancel() }
}.flowOn(Dispatchers.IO).shareIn(viewModelScope, SharingStarted.Lazily)
}
在您的片段初始视图模型中,您的视图模型取决于父活动:
class FirstFragment : Fragment() {
private val viewModel by activityViewModels<SocketViewModel>()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.socketEventsFlow.collectLatest {
// TODO get event and do what you want to to
}
}
}
return inflater.inflate(
R.layout.fragment_first,
container,
false
)
}
}
活动代码:
class MainActivity : AppCompatActivity() {
private val viewModel by viewModels<SocketViewModel>()
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.socketEventsFlow.collectLatest {
// TODO get event and do what you want to to
}
}
}
}
}