Create a gist now

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Kotlin Coroutines でリトライをしながら通信を試行する
package com.example.tomoyashibata.myapplication
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.util.Log
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.experimental.CommonPool
import kotlinx.coroutines.experimental.android.UI
import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.launch
import java.io.IOException
import java.net.URL
import kotlin.coroutines.experimental.suspendCoroutine
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
launch(UI) {
try {
val bitmap = this@MainActivity.loadAvatarImage()
this@MainActivity.avatarImageView.setImageBitmap(bitmap)
} catch (e: IOException) {
// エラーを Toast で表示
Toast.makeText(this@MainActivity, e.toString(), Toast.LENGTH_LONG).show()
}
}
}
private suspend fun loadAvatarImage(): Bitmap = suspendCoroutine { cont ->
// URL から末尾の .jpg を取り除いてわざとエラーが起こるようにしている
val urlConnection = URL("https://pbs.twimg.com/profile_images/637494283365298177/J0t3qvlm_400x400").openConnection()
launch(CommonPool) {
try {
val bitmap = retryIO(times = 10) {
urlConnection.connect()
val stream = urlConnection.getInputStream()
BitmapFactory.decodeStream(stream)
}
cont.resume(bitmap)
} catch (e: IOException) {
cont.resumeWithException(e)
}
}
}
// リトライ用メソッド
// https://stackoverflow.com/questions/46872242/how-to-exponential-backoff-retry-on-kotlin-coroutines
suspend fun <T> retryIO(
times: Int = Int.MAX_VALUE,
initialDelay: Long = 100,
maxDelay: Long = 1000,
factor: Double = 2.0,
block: suspend () -> T): T {
var currentDelay = initialDelay
repeat(times - 1) {
try {
return block()
} catch (e: IOException) {
Log.e("IOException: ", e.toString())
}
delay(currentDelay)
currentDelay = (currentDelay * factor).toLong().coerceAtMost(maxDelay)
}
return block()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment