Fragment에서의 Activity와 Context의 구분

9425 단어 안드로이드Kotlin

소개



Fragment에 있어서의 ActivityContext 의 의미나 구분을 모르기 때문에, 조사해 보았습니다.

결론


  • Context 으로 끝난다
  • null 허용 → this.context
  • null를 허용하지 않는다 → requireContext()

  • Activity 를 건네줄 필요가 있다
  • null 허용 → this.activity
  • null를 허용하지 않는다 → requireActivity()


  • 환경


  • OS: macOS Big Sur 11.1
  • Android Studio: 4.1.2
  • Kotlin: 1.4.20
  • Gradle: 6.8
  • Gradle plugin: 4.1.2
  • Timber: 4.7.1

  • 조사



    각 처리의 반환값



    Fragment에서 다음을 수행했습니다.

    MonsterListFragment.kt
    Timber.d("${this.activity}")
    Timber.d("${requireActivity()}")
    Timber.d("${this.context}")
    Timber.d("${requireContext()}")
    

    Logcat의 출력 결과
    2021-03-06 19:07:40.162 24680-24680/com.theuhooi.uhooipicbook D/MonsterListFragment: com.theuhooi.uhooipicbook.MainActivity@95e20bb
    2021-03-06 19:07:40.162 24680-24680/com.theuhooi.uhooipicbook D/MonsterListFragment: com.theuhooi.uhooipicbook.MainActivity@95e20bb
    2021-03-06 19:07:40.163 24680-24680/com.theuhooi.uhooipicbook D/MonsterListFragment: dagger.hilt.android.internal.managers.ViewComponentManager$FragmentContextWrapper@e47f888
    2021-03-06 19:07:40.166 24680-24680/com.theuhooi.uhooipicbook D/MonsterListFragment: dagger.hilt.android.internal.managers.ViewComponentManager$FragmentContextWrapper@e47f888
    
    this.activityrequireActivity() , this.contextrequireContext()의 출력은 동일합니다.
    즉 동일한 인스턴스를 반환합니다.

    require○○() vs this.○○


    requireActivity()requireContext() 의 구현을 살펴 보겠습니다.

    Fragment.java
    /**
     * Return the {@link FragmentActivity} this fragment is currently associated with.
     *
     * @throws IllegalStateException if not currently associated with an activity or if associated
     * only with a context.
     * @see #getActivity()
     */
    @NonNull
    public final FragmentActivity requireActivity() {
        FragmentActivity activity = getActivity();
        if (activity == null) {
            throw new IllegalStateException("Fragment " + this + " not attached to an activity.");
        }
        return activity;
    }
    

    Fragment.java
    /**
     * Return the {@link Context} this fragment is currently associated with.
     *
     * @throws IllegalStateException if not currently associated with a context.
     * @see #getContext()
     */
    @NonNull
    public final Context requireContext() {
        Context context = getContext();
        if (context == null) {
            throw new IllegalStateException("Fragment " + this + " not attached to a context.");
        }
        return context;
    }
    

    보시다시피, activity (context)null이면 예외가 발생하고 null가 아니면 인스턴스를 반환하는 간단한 구현입니다.

    전달할 대상이 null 를 허용하는 경우 null 의 오류 처리를 맡길 수 있으므로 require○○() 를 호출하지 않고 this.○○ 로 전달해야 한다고 생각합니다.require○○() 를 호출하면 예외가 발생해, 그 외로 핸들링할 수 없게 되기 때문입니다.

    반대로 null가 아닌 contextactivity가 필요한데 require○○()를 사용하지 않는 것은 중복이므로 피해야합니다.

    MonsterListFragment.kt
    class MonsterListFragment : Fragment() {
        override fun onOptionsItemSelected(item: MenuItem): Boolean {
            // ×冗長
            this.context?.let {
                MaterialAlertDialogBuilder(it)
            }
    
            // ○簡潔
            MaterialAlertDialogBuilder(requireContext())
        }
    }
    

    Activity vs Context



    출력 결과와 require○○() 메서드의 구현에서 Fragment가 가지는 activity 의 형태는 FragmentActivity , context 의 형태는 Context 라는 것을 알았습니다.
    FragmentActivity 의 상속을 따라가면 Context 에 도착합니다.
    Context
    ↑
    ContextWrapper
    ↑
    ContextThemeWrapper
    ↑
    Activity
    ↑
    androidx.core.app.ComponentActivity
    ↑
    ComponentActivity
    ↑
    FragmentActivity
    

    가능한 한 작게 끝내고 싶기 때문에, Context 로 끝나는 곳에 Activity 를 건네줄 필요는 없다고 생각합니다.

    Context 유형


    FragmentActivity 의 상속도로부터 ActivityContext 의 자손인 것을 알았습니다.

    마찬가지로 ApplicationContext의 자손임을 알 수 있습니다.
    Context
    ↑
    ContextWrapper
    ↑
    Application
    

    Context를 구별하기 위해, Application를 「Application Context」, Activity를 「Activity Context」라고 부르는 경우가 있습니다.

    Fragment에서 얻을 수 있는 Context는 「Activity Context」이며, 「Application Context」는 Activity를 개입하지 않으면 취득할 수 없습니다(잘못되어 있으면 지적해 주세요).Activity 에서 this.applicationContext 에서 Application Context를 얻을 수 있습니다.

    Application Context 쪽이 생존 기간이 길기 때문에 안전합니다.
    그러나 기본적으로는 Activity의 라이프 사이클에 따라 Activity Context를 사용하는 것이 좋을 것 같습니다.

    검증되지 않았지만 Fragment의 this.activitythis.context는 동일한 인스턴스 (이번에는 MainActivity)를 참조하는 것으로 보입니다.

    즉 기본적으로 어느 것을 사용해도 변하지 않습니다.this.activitythis.context 의 내용이 다르거나 한쪽만 null 가 되는 케이스가 있는지 궁금합니다.

    결론



    본 기사의 내용은 어디까지나 내가 내놓은 결론입니다.
    다른 의견이나 지적 등이 있으시면 언제든지 코멘트 등을 부탁드립니다.

    참고 링크


  • 안드로이드 기초 지식 - mixi-inc/AndroidTraining
  • Android에서 사용되고 있는 Application Context와 Activity Context의 사용소 정리. - GA technologies GROUP Tech Blog
  • htps : // 라고 해서 r. 이 m/테ぇ_우호오이/s타츠 s/1368107727961026563? s=20
  • htps : // 라고 해서 r. 이 m/yt8492/s타츠 s/1368113367412473860? s=20
  • htps : // 라고 해서 r. 이 m/테ぇ_우호오이/s타츠 s/1368208335703449603? s=20
  • 좋은 웹페이지 즐겨찾기