iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 23
0
Mobile Development

老姐好像要用 Kotlin 寫專案,能撐30天嗎?系列 第 23

一改再改的第二十三天:聊天室範例拼接(下)

經過一晚的休息,老姐找到了癥結。

https://ktor.io/docs/clients-websockets.html 的範例沒有問題,有問題的是 Library。

老姐抱怨:「還以為 android 該用 ktor-client-android 結果被坑了。」

    implementation "io.ktor:ktor-client-android:$ktor_version"

試過之後發現 okhttpcio 哪個都可以,老姐就選了老搭檔 okhttp。

    implementation "io.ktor:ktor-client-okhttp:$ktor_version"
    implementation "io.ktor:ktor-client-cio:$ktor_version"

因為之前的範例是寫死訊息,所以改參考另一個範例,可以將連線和送訊息分開: https://github.com/ktorio/ktor-samples/tree/master/generic/samples/chat/src/frontendMain/kotlin

    private val wsClient = WsClient(HttpClient { install(WebSockets) }, ::notifyMessage)
    private fun notifyMessage(message: String) {
        //MutableLiveData update ui
    }
class WsClient(private val client: HttpClient,
        private val onReceive: (input: String) -> Unit) {
        var session: WebSocketSession? = null

        suspend fun connect() {
            session = client.webSocketSession(
                method = HttpMethod.Get,
                host = "192.168.48.3",
                port = 8080,
                path = "/ws"
            )
        }

        suspend fun send(message: String) {
            session?.send(Frame.Text(message))
        }

        suspend fun receive(onReceive: (input: String) -> Unit) {
            while (true) {
                val frame = session?.incoming?.receive()

                if (frame is Frame.Text) {
                    onReceive(frame.readText())
                }
            }
        }
    }

輸入訊息。
https://ithelp.ithome.com.tw/upload/images/20201002/2012919700sP95RN2V.png
成功收到 server echo 。
https://ithelp.ithome.com.tw/upload/images/20201002/20129197BVVzXwUT2g.png
別人傳的的訊息也能收到。
https://ithelp.ithome.com.tw/upload/images/20201002/20129197y4gL6UNkqw.png

「太好了!老姐,妳做到了!」趕快稱讚老姐一下,連假日都在寫個人專案,這次應該能達到終點。

但老姐並沒有開心,而是不甚滿意的說:「如果用這個 library ,中途斷線有點被動⋯⋯,而且萬一將來不用 ktor ,可能要改程式碼。」

說著就直接打開 okhttp 官網,開始改裝。 https://square.github.io/okhttp/4.x/okhttp/okhttp3/-web-socket/
https://ithelp.ithome.com.tw/upload/images/20201002/20129197ZjWz27EufG.png

implementation 'com.squareup.okhttp3:okhttp:3.14.7'

為了能重用剛剛的介面,寫成同樣的外型。

    private val wsClient = WsClient(
        OkHttpClient.Builder()
            .pingInterval(60, TimeUnit.SECONDS)
            .build(), ::notifyMessage
    )
    private fun notifyMessage(message: String) {
        //MutableLiveData update ui
    }
class WsClient(
        private val client: OkHttpClient,
        private val onReceive: (input: String) -> Unit
    ) {
        var session: WebSocket? = null

        fun connect() {
            val request = Request.Builder()
                .url("ws:192.168.48.3:8080/ws")
                .build()
            client.newWebSocket(request, object:WebSocketListener() {
                override fun onOpen(webSocket: WebSocket, response: Response?) {
                    session = webSocket
                }

                override fun onMessage(webSocket: WebSocket, text: String) {
                    onReceive(text)
                }

                override fun onMessage(webSocket: WebSocket, bytes: ByteString) {
                }

                override fun onClosing(
                    webSocket: WebSocket,
                    code: Int,
                    reason: String
                ) {
                }

                override fun onClosed(
                    webSocket: WebSocket,
                    code: Int,
                    reason: String
                ) {
                }

                override fun onFailure(
                    webSocket: WebSocket?,
                    t: Throwable,
                    response: Response?
                ) {
                }
            })
        }

        fun send(message: String) {
            session?.send(message)
        }
    }

看到 App 呈現和剛剛一樣的成功結果,終於能放下心來。

我想了想,和老姐說:「多房間就後面再加,我們看看還沒有什麼有難度的功能先做一做。」

老姐大力贊成:「太好了,我也這麼想,畫面有好多要改,但是都可以緩緩,功能更重要。」

哼哼,我是怕妳一直寫相似的東西容易膩啊,都到這裡了,可不想功虧一簣。

而且老姐呀, ktor okhttp engine 裡面的 config block 是 OkHttpClient.Builder ,所以設置上不會差異太多,頂多是斷線和收更新的地方不同,和版本會比最新的 okhttp 慢 。至於 Android engine 不能用 ws protocol 肇因於裡面包的是 HttpURLConnection 。

https://ktor.io/docs/http-client-engines.html#jvm-and-android
https://ithelp.ithome.com.tw/upload/images/20201003/201291974ixii2HgVX.png

本次鐵人賽的作品在放進更多內容後已經成書,書名是《老姐要用Kotlin寫專案:從 Server 到 Android APP 的開發生存日記》,歡迎購買唷。https://www.tenlong.com.tw/products/9789864348978


上一篇
各自努力的第二十二天:聊天室範例拼接(上)
下一篇
專案會議的第二十四天:獨立支付系統 v.s in app purchase
系列文
老姐好像要用 Kotlin 寫專案,能撐30天嗎?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言