Skip to content

Instantly share code, notes, and snippets.

@TomoyaShibata
Last active September 8, 2018 10:56
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TomoyaShibata/9c4846717cc2926496295d654111b543 to your computer and use it in GitHub Desktop.
Save TomoyaShibata/9c4846717cc2926496295d654111b543 to your computer and use it in GitHub Desktop.
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