はじめに
Contextについて自分なりに調べて学んだので記事に残します。
きっかけとしては、
Android開発をしていて、何も考えずにContextをメソッドの引数に渡しまくっていたところ、リードエンジニアにこのようなレビューを受けたことがある。
Contextの過剰摂取には気をつけましょう。
いつの間にか抜け出せなくなっていずれ手のつけようがなくなってしまいます。
引数にContextを追加したら負けぐらいの気持ちでContextを引数に追加しないことを意識したほうが良いです。
そこで「Contextって何??」っと思って色々調べた。
そもそも Context とは??
日本語の意味的なContext
(文章の)前後関係、文脈、脈絡、背景、状況、環境
などと出てくる
プログラミングにおけるContext
こちらのサイトから抜粋
http://e-words.jp/w/%E3%82%B3%E3%83%B3%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88.html
プログラミングの分野でも、同じコード記述やプログラム上の要素が、その置かれているプログラム内での位置や、実行される際の内部状態などによって異なる振る舞いをしたり、異なる制約を受けたりすることを指してコンテキストということがある。
Android開発におけるContext
クラス定義と継承関係
- Contextは抽象クラスで定義されている
- Activityのスーパークラス(ActivityがContextクラスを継承している)
- 継承関係:
Context
←ContextWrapper
←ContextThemeWrapper
←Activity
- 継承関係:
- Applicationのスーパークラス(ApplicationがContextクラスを継承している)
- 継承関係:
Context
←ContextWrapper
←Application
- 継承関係:
ちなみにContextWrapperクラス
にgetApplicationContext()
が定義されてる
どんなときに登場、利用するか
- Dialog生成時
- Intent利用時
- アプリケーションのリソースにアクセスする際(例:
getString()
など)
などなど... とにかく神出鬼没
どうやら大きく2種類のContextがあるらしい(他にもあるようだが今回は割愛)
ActivityのContext
- Activityのライフサイクルに依存する。そのためActivityが破棄されるとき(画面回転時など)はContextも同様に破棄される。
- インスタンスはシングルトンではないようである。
取得方法
-
Java
Activity: this
View, Fragment: getContext(), requireContext()
-
Kotlin
Activity: this
View, Fragment: context, requireContext()
getContext()とrequireContext()の違い
-
getContext()
: null値許容 (Kotlinでは Context? として扱う)のContextを値として返す -
requireContext()
: 非nullのContextを値として返す
参考資料
- https://stackoverflow.com/questions/60402490/difference-between-getcontext-and-requirecontext-when-using-fragments
- https://developer.android.com/kotlin/common-patterns?hl=ja
ApplicationのContext
- アプリケーションに関連していて、Activityのライフサイクルに依存しない。
- シングルトンとしてアプリケーションが生きている間は破棄されたり変更されたりしない。
取得方法
Java: getApplicationContext()
Kotlin: applicationContext
どうやって使い分けるのが望ましいのか?
結論としては、「ライフサイクルとメモリリークの危険性を考慮した上で実装する」という抽象的なものになってしまった。
だが、基本的にはメモリリークの危険性を考慮して極力ActivityContext
を使う方が良さそう。
複数の記事を参考にしましたが、いろいろな意見がありました。
メモリリークについてContextの取り扱いにおいての注意事項
- Contextの寿命が受け取る側のオブジェクトの寿命より長くなる場合: 好ましい実装
- Contextの寿命より受け取る側のオブジェクトの寿命が長くなる場合: メモリリークの危険がある
じゃあ今後Contextに出くわしたらどうする?
今までは何も考えずに適当にContext
を利用していたが、今後はこの場面では「ActivityContext
とApplicationContext
どちらを使うのがベターなのだろう?」と考えながら実装していこうと思います。
その中で理解を深めいく。
※ 自分自身の実力不足で色々と抜け漏れがあるかもです。精進します。
スペシャルサンクス(参考にさせていただいた資料)
- https://qiita.com/iduchikun/items/34b3ae26cfc438e7e5dc
- https://tech.ga-tech.co.jp/entry/2020/06/android-contexts
- https://www.lanches.co.jp/blog/9776
- https://developer.android.com/reference/android/content/Context?hl=ja
- http://mitoroid.com/category/android/android_context.php
- https://qiita.com/k-yamada-github/items/bd99f45ed0d7176d2612
- https://qiita.com/roba4coding/items/0585b8240873ec5e9c20
- https://blog.meilcli.net/2018/12/26/185752
- https://blog.meilcli.net/2018/12/26/185752
最後に
間違い、ご指摘などありましたらぜひともコメントいただきたいです!
最後に結論として、Context難しい...
ありがとうございました。