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

コメント

このブログの人気の投稿

目覚まし時計アプリを公開します

超初心者の機械学習入門

画面回転で苦労した話(原因はわかった)