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()というのを使って解放する。これでメモリリークは出なくなった。ふう。
コメント
コメントを投稿