kotlinのコルーチンを使って、Webアクセスを含めた非同期処理を実装してみます。
下準備としてGradleにライブラリを追加します。
// For Coroutine
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
ViewModelの中に非同期処理を書いていきます。
//コルーチンスコープ内で呼び出す
@UiThread
private fun getURLInfo(){
viewModelScope.launch {
val result = connect()
decodeJson(result)
}
}
connectはワーカースレッドでWebアクセス処理を行い、decodeJSONはUIスレッドでString文字列の解析を行います。
別々のスレッドで行う処理を1つの非同期処理ブロックとして記載します。
connectは以下のようにsuspendをつけることで、非同期処理なんだけど、connectの処理が終わってデータをダウンロードした後に、decodeJsonを行うことができます。
//URLに接続する。suspendを使うことで他の処理を中断させることができる。
@WorkerThread
private suspend fun connect():String{
//ワーカースレッドとしてスレッド分離する
val returnVal = withContext(Dispatchers.IO){
var result = ""
val url = URL(url)
val con = url.openConnection() as? HttpURLConnection
con?.let {
try {
it.connect()
val stream = it.inputStream
result = iStreamToString(stream)
println(result)
stream.close()
}catch (err:SocketTimeoutException){
println(err)
}
it.disconnect()
}
result
}
return returnVal
}
接続した結果はInputStreamで得られるので、Stringに変換する関数を以下の通り作ります。
また、JSONをデコードする関数をUIスレッドで宣言します。(Json解析の中身は別の記事で書こうと思いますが、ここでUIの更新を行い、文字列の表示などをします。)
//InputStreamをStringに変換する
private fun iStreamToString(stream:InputStream):String{
val sb = StringBuilder()
val reader = BufferedReader(InputStreamReader(stream,"UTF-8"))
var line = reader.readLine()
while (line != null){
sb.append(line)
line = reader.readLine()
}
reader.close()
return sb.toString()
}
@UiThread
private fun decodeJson(result:String){
//JSONの解析をする
}