Handlerによるメモリリークが修正できた件
時計アプリを作っていた際に遭遇したメモリリーク。1秒ごとに、現在時刻をtvTimeNowというTextViewに表示するような簡単なプログラムだが、LeakCanaryで調べるとメモリリークがあることが判明した。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_zmain)
val handler = Handler(Looper.getMainLooper())
val refresh = object : Runnable {
override fun run() {
//時刻を表示
val now = Calendar.getInstance()
tvTimeNow.text=
"${now.get(Calendar.HOUR_OF_DAY)}:${String.format("%02d", now.get(Calendar.MINUTE))}"
handler.postDelayed(this, 1000)
}
}
handler.post(refresh)
}
}
メモリリークについてよくわかっているとは言えないのだが、LeakCanaryによるとこのrefreshのところでリークがあるらしい。それで、これを解放するコードを書けばいいのか・・・?と試行錯誤してつぎのようになった。
class MainActivity : AppCompatActivity() {
lateinit var handler: Handler
lateinit var refresh: Runnable
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_zmain)
handler = Handler(Looper.getMainLooper())
refresh = object : Runnable {
override fun run() {
//時刻を表示
val now = Calendar.getInstance()
tvTimeNow.text= "${now.get(Calendar.HOUR_OF_DAY)}:${String.format("%02d", now.get(Calendar.MINUTE))}"
handler.postDelayed(this, 1000)
}
}
handler.post(refresh)
}
override fun onDestroy() {
super.onDestroy()
handler.removeCallbacks(refresh)
}
}
MainActivityの直下でhandlerとrefreshをlateinit var で宣言し、最後にonDestroy()でremoveCallbacks()というのを使って解放する。これでメモリリークは出なくなった。ふう。
コメント
コメントを投稿