【问题标题】:How to create shared webSocket for two fragments and one activity?如何为两个片段和一个活动创建共享 webSocket?
【发布时间】:2022-01-04 11:55:28
【问题描述】:

现在我的应用程序只有一个活动,它完全支持带有侦听器的 WS 操作并创建新的 webSocket 实例。我想将其分解为一个活动,该活动就像是多个片段的持有者。

一开始我想在活动中创建 webSocket,然后在片段上使用创建的 webSocket。我使用 okHttp3 websockets。一般来说,我可以创建一个单独的 viewModel,我将在其中初始化 websocket,但我还需要在 WS 创建期间传递侦听器:

val loggingInterceptor: HttpLoggingInterceptor = HttpLoggingInterceptor()
            .setLevel(HttpLoggingInterceptor.Level.BODY)


val client = OkHttpClient.Builder()
            .addInterceptor(AuthToken(this))
            .addInterceptor(loggingInterceptor)
            .build()

val request = Request.Builder()
            .url(
                BuildConfig.CHAT_URL + UtilsClass.userInfo.applicant?.id + "/"
            )
            .addHeader("Sec-WebSocket-Protocol","android")
            .build()


val ws = client.newWebSocket(request, listener) <---- here

另一方面,我需要为单独的片段设置单独的侦听器。 .newWebSocket(... 的调用将创建一个新的 webSocket 实例,这对我不利。但是,当我将拥有一个共享的 webSocket 侦听器时,我将需要处理我等待信息的片段。另外,也许我决定做一件不好的事情。

【问题讨论】:

    标签: android android-fragments websocket


    【解决方案1】:

    要使用此解决方案,您必须熟悉这些基础知识

    1. MVVM 架构
    2. 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
                    }
                }
            }
         }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多