마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

뷰모델 팩토리패턴 사용이유

0 추천

팩토리패턴에 관해서 찾아봤으나 의문이 해결이 안되서 질문합니다

찾아보면 이럴때 팩토리패턴을 사용한다고 하는데..

 

어떤 클래스가 자신이 생성해야 하는 객체의 클래스를 예측할 수 없을 때

생성할 객체를 기술하는 책임을 자신의 서브클래스가 지정했으면 할 때

해당하는 예시가 뭐가있을지도 잘모르겠고.

factory = CalcViewModelFactory(MyCalc())
viewModel = ViewModelProvider(this, factory).get(CalcViewModel::class.java)

viewModel = ViewModelProvider(this).get(CalcViewModel::class.java)

팩토리패턴을 써서 만들경우와 안써서 만들경우 

저렇게 코드가 있다면, 팩토리패턴에서 뷰모델 인스턴스를 생성해서 리턴과

팩토리패턴안쓰고 뷰모델 인스턴스를 생성하는 것아닌가요..? 결국 둘다 뷰모델 인스턴스를 생성하는 거같은데 두개의 차이를 잘 모르겠습니다. 팩토리 패턴을 정확히 왜써야하는지 글을 봤지만,  해당 사례?가 어떤게 있는지 잘모르겠습니다

수원통학러 (3,570 포인트) 님이 2021년 8월 30일 질문

1개의 답변

0 추천
factory 를 인자로 전달하지 않을 경우는 안드로이드가 디폴드 ViewModelFactory를 사용합니다. 이유는 라이프사이클과 관련이 있습니다. 아시다시피 ViewModel 은 configuration change에도 살아 남도록 설계가 되었기 때문에 이렇게 하려면 어딘가에 ViewModel 에 다시 살릴 수 있도록 처리를 해야 하는데, ViewModelStore라는 클래스가 실질적으로 그 역할을 담당합니다. ViewModel은 Activity나 Fragment같은 ViewModelStoreOwner들이 생성된 ViewModel을 소유하게 되어 있습니다. 따라서 Activity나 Fragment가 configuration change에 띠라 다시 생성될 때, ViewModelStoreOwner에 대한 정보를 저장하고 있다가, 거기에 매핑된 ViewModelStore로부터 ViewModel를 가져오게 됩니다. 이 과정이 생각보다 좀 복잡한데, 이런 복잡한 생성과정을 단순한 ViewModel 생성자로는 처리할 수 없기 때문에 잘 알려진 디자인 패턴 중의 하나인  Factory 패턴을 이용해 ViewModel을 생성하게 된 겁니다.

그리고 커스텀 팩토리를 사용하는 경우로는 Dependency Injection을 사용하는 경우를 대표적으로 들 수 있습니다. 안드로이드가 제공하는 디폴트 클래스로는 필요한  dependency들을 inject할 수 없기 때문에 이런 경우는 별도로 만들어 사용해야 합니다.

도움이 되시길. 바래요.
spark (226,420 포인트) 님이 2021년 8월 30일 답변
말씀하시는 디폴트 뷰모델팩토리랑 커스텀 팩토리가 어떤건지 알수있을까요?
ViewModelProvider.Factory 상속받고

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return CalcViewModel(calculations) as T
    }
이렇게되는 애가 디폴트인지 커스텀인지..모르겠네요
안드로이드 소스코드를 직접 보시는게 더 빠르실 것 같아요.

ViewFactory를 전달하지 않으면, 아래처럼
public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
        if (mFragmentManager == null) {
            throw new IllegalStateException("Can't access ViewModels from detached fragment");
        }
        if (mDefaultFactory == null) {
            Application application = null;
            Context appContext = requireContext().getApplicationContext();
            while (appContext instanceof ContextWrapper) {
                if (appContext instanceof Application) {
                    application = (Application) appContext;
                    break;
                }
                appContext = ((ContextWrapper) appContext).getBaseContext();
            }
            if (application == null && FragmentManager.isLoggingEnabled(Log.DEBUG)) {
                Log.d(FragmentManager.TAG, "Could not find Application instance from "
                        + "Context " + requireContext().getApplicationContext() + ", you will "
                        + "not be able to use AndroidViewModel with the default "
                        + "ViewModelProvider.Factory");
            }
            mDefaultFactory = new SavedStateViewModelFactory(
                    application,
                    this,
                    getArguments());
        }
        return mDefaultFactory;
    }

이 함수를 내부적으로 호출하게 되어있어요. 그리고 커스텀 클래스란게 별도로 ViewModelProvider.Factory를 넘겨주면 다 커스텀이 되겠죠, 안드로이드 디폴트값을 사용하지 않으니까요.
...