内容
Android開発時にFragmentにHiltの @AndroidEntryPoint
アノテーションを付けてインジェクションを行った際、requireContextを呼んだ場合など context の中身が ViewComponentManager.FragmentContextWrapper
になる。
これの何が問題かというと、これまで contextの中身はActivityと相場が決まっていたので if (context is Activity)
やら context as Activity
などが随所に書かれているが、これがfalseになったりクラッシュしたりする。
対応(新)
HiltはActivityのContextを取得する方法を提供してくれている。
@AndroidEntryPoint class SampleFragment : Fragment() { @Inject @ActivityContext lateinit var activityContext: Context
対応(旧)
こちらは対応(新)を知らなかったときの古い記述です。残しておきますがご参考まで。
FragmentContextWrapper
は baseContextという形でcontextを保持している。なのでbaseContextがActivityかどうかをチェックするようにしてあげる必要がある。
なのでContextクラスに hiltBaseContext
プロパティを拡張してみた。
val Context.unwrapppedContext: Context get() { return if (this is ViewComponentManager.FragmentContextWrapper) { this.baseContext } else { this } } fun hoge(context: Context) { if(context.unwrapppedContext is Activity) { // do something } }
Context.baseContext
という風にプロパティ名をそのまま使うと実装をミスった場合に
ContextWrapper.getBaseContext()が直接呼ばれてしまう場合があるので unwrapppedContext
としてみたが
長くていまいちしっくりこない。
あとcontextがactivityかどうかのチェック時に常にbaseContextを意識しないといけないのが難点。