AndroidのViewに自動更新ロジックを埋め込む時に、ActivityやFragmentのonResume/onPauseに当たるコールバックを受け取りたい時があるかと思います。
そういう場合はView.onVisibilityChangedやView.onWindowFocusChangedなどを使いましょう、というメモです。
Viewのライフサイクル
Viewのライフサイクルはこちらの記事に詳しいです。
- onFinishInflate()
- onMeasure()
- onLayout()
- onDraw()
- onAttachedToWindow()
- onDetachedFromWindow()
などのイベントがあります。
この中で、onAttachedToWindow()がActivity.onCreate()に、onDetachedFromWindow()がActivity.onDestroy()にほぼ、対応しているのかな、と思われます。
Viewの表示、非表示
Activityに更新ロジックやイベントコールバックを登録・解除する時はonResume()/onPause()で行うことが多いかと思います。
Viewの場合はこちらの回答の一つを参考にすると、View.onVisibilityChanged()もしくはonWindowFocusChanged()を確認することで、検知できそうです。
@Override
protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
switch (visibility){
case VISIBLE://onResume called
case INVISIBLE:// onPause() called
}
}
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
if (hasWindowFocus) //onresume() called
else // onPause() called
}
Activityから直接イベントを通知する方が確実ですが、Viewの表示されている間だけ自動更新を行いたい、というケースだとonVisibilityChangedは適切ですね。
ただ、このonVisibilityChangedはViewのvisibilityを動的に変更している場合などにも発火されるので、一時的な非表示時にも更新したい場合は注意が必要です。
更新ロジックのタイミング
onResume/onPauseでコールバックやスレッドの開始・停止処理を行うのは、Activityがフロント・バックグラウンドの変化をおおむねトリガーして発行されるイベントで、他のアプリが立ち上がっている最中に無駄な表示更新ロジックを行わないための工夫かと思います。
Viewの場合は、ライフサイクル上のコールバックでは表示・非表示を確認できません。
例えば、onAttachedToWindow()・onDetachedFromWindow()では、二つの間でもホームボタン等でActivityがバックグラウンドに存在するケースも存在します。
表示・非表示という状態変化イベントをトリガーにして処理を行うのがいいですね。
外部とやりとりするロジックは分離する
もちろん、ネットワークやデータベースなど、他のサービスとのやりとりなどが含まれるケースでは、Viewではなくコントローラー等にロジックを寄せる方がいいでしょう。
なので、このようなイベントで処理を書くケースは少ないのかもしれません。