프래그먼트 onAttach - peulaegeumeonteu onAttach

TL;DR: 

Fragment 에서 아래와 같이 viewModel 생성했을 때, onAttach() 메서드가 호출된 이후에  viewModel 에 접근해야 한다. 

private val viewModel by viewModels<YourViewModel>()

올바른 접근 (⭕️)

override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) arguments?.apply { viewModel.initAddTask(getInt(ARG_TASK_ID).toLong()) } }

올바르지 않은 접근 (❌)

override fun onAttach(context: Context) { super.onAttach(context) arguments?.apply { viewModel.initAddTask(getInt(ARG_TASK_ID).toLong()) } }

🚧 바로 위의 예제와 같이, onAttach() 내에서 viewModel 에 접근하면, 아래와 같은 오류를 마주칠 것이다. 

java.lang.IllegalStateException: You can consumeRestoredStateForKey only after super.onCreate of corresponding component

오류가 발생하는 이유 

Fragment.viewModels() 의 내부 구현체를 보자. 

주석을 살펴보면,

This property can be accessed only after this Fragment is attached i.e., after* [Fragment.onAttach()]

이 프로퍼티(viewModel) 은 fragment 가 attached 된 이후에 접근 가능하다 라고 쓰여있다. 

어떻게 보면 당연하다고 생각되는 것이, viewModels() 로 생성 시 viewModel 의 default scope(기본 범위)가 해당 fragment 이기 때문에.

* * This property can be accessed only after this Fragment is attached i.e., after * [Fragment.onAttach()], and access prior to that will result in IllegalArgumentException. */ @MainThread inline fun <reified VM : ViewModel> Fragment.viewModels( noinline ownerProducer: () -> ViewModelStoreOwner = { this }, noinline factoryProducer: (() -> Factory)? = null ) = createViewModelLazy(VM::class, { ownerProducer().viewModelStore }, factoryProducer)

단, activityViewModels() 로 생성 후 접근하면 오류가 발생하지 않는다. 

Fragment 에서 아래와 같이 activityViewModels 로 생성하면 onAttach() 에서 viewModel 에 접근해도 위와 같은 오류는 발생하지 않았다. 

private val viewModel by activityViewModels<YourViewModel>()

실제로 activityViewModels 의 내부 구현체를 보면, viewModels 와 동일하게 onAttach() 후에 접근해야 한다고 쓰여 있으나, 

* This property can be accessed only after this Fragment is attached i.e., after * [Fragment.onAttach()], and access prior to that will result in IllegalArgumentException. */ @MainThread inline fun <reified VM : ViewModel> Fragment.activityViewModels( noinline factoryProducer: (() -> Factory)? = null ) = createViewModelLazy(VM::class, { requireActivity().viewModelStore }, factoryProducer ?: { requireActivity().defaultViewModelProviderFactory })

실제로 테스트했을 때 정상적으로 동작한 이유는,

activityViewModels 로 viewModel 을 생성한다는 것은 fragment 의 parent activity scope의 viewModel 을 사용하는 것으로, parent activity 는 이미 생성되어 있는 상태기 때문에 별다른 exception 없이 동작한 것으로 생각된다. 

주요 콘텐츠로 건너뛰기

이 브라우저는 더 이상 지원되지 않습니다.

최신 기능, 보안 업데이트, 기술 지원을 이용하려면 Microsoft Edge로 업그레이드하세요.

Activity.OnAttachFragment(Fragment) Method

  • Reference

Definition

In this article

Called when a Fragment is being attached to this activity, immediately after the call to its Fragment#onAttach Fragment.onAttach() method and before Fragment#onCreate Fragment.onCreate().

[Android.Runtime.Register("onAttachFragment", "(Landroid/app/Fragment;)V", "GetOnAttachFragment_Landroid_app_Fragment_Handler")] [System.Obsolete("deprecated")] public virtual void OnAttachFragment (Android.App.Fragment? fragment);[<Android.Runtime.Register("onAttachFragment", "(Landroid/app/Fragment;)V", "GetOnAttachFragment_Landroid_app_Fragment_Handler")>] [<System.Obsolete("deprecated")>] abstract member OnAttachFragment : Android.App.Fragment -> unit override this.OnAttachFragment : Android.App.Fragment -> unit

Parameters

Attributes

Remarks

Java documentation for android.app.Activity.onAttachFragment(android.app.Fragment).

Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.

Applies to

티스토리 뷰

아래는 코모스튜디오가 직접 만든 무료 앱이에요

(한 번만 봐주세요 ^^)

01

02

03

정각알림 만들기(말하는시계)

말하는 시계 (취침, 자전거) 

말하는 타이머 음성 스톱워치 

프레그먼트 생명 주기

실행 시

onAttach —> onCreate() —> onViewCreated() —> onActivicyCreated() —> onResume()

해제시

onPause() — > onDestroyView() — > onDestroy() —> onDetach()

즉,

안전하게 context 를 사용 하려면

    @Override

    public void onAttach(Context context) {

        super.onAttach(context);

        mContext = context;

    }

요렇게 해서 사용한다.

프래그먼트 이곳 저곳에서 getContext(), getActivity() 를 부르다가  Null 이 발생할 수 있기 때문에 이렇게 부르는 것이 안전. 더 안전 하려면 부를 때마다 체크 하는게 더 안전. 

isAdd() && mContext != null 

모든 게시물은 코모스튜디오의 소유이며, 무단 복제 수정은 절대 불가입니다.
퍼가실 경우 댓글과 블로그 주소를 남기고 해당 게시물에 출처를 명확히 밝히세요.

Toplist

최신 우편물

태그