til

day 24

paulaner80 2022. 1. 13. 12:11
반응형

참고 : 

https://readystory.tistory.com/176

 

 

 

 

ViewModel ViewModelStore 라는 객체에서 관리를 합니다.

ViewModelStore ViewModelStoreOwner라는 객체에서 관리를 합니다.

 

ViewModelStoreOwner는 인터페이스이고 액티비티와 프래그먼트가 바로 이 ViewModelStoreOwner 를 구현하고 있습니다.

그래서 ViewModel 객체를 생성할 때 Owner(액티비티나 프래그먼트)를 인자로 받고, Owner에 따라 ViewModel Scope 가 결정됩니다.

 

https://miro.medium.com/max/700/0*Io9CAKKPaZbZH1Q0.png

 

1.ViewModelProvider를 통해 ViewModel 인스턴스를 요청한다.

2. ViewModelProvider 내부에서는 ViewModelStoreOwner를 참조하여 ViewModelStore를 가져온다.

3. ViewModelStore에게 이미 생성된(저장된) ViewModel 인스턴스를 요청한다.

4. 만약 ViewModelStore가 적합한 ViewModel 인스턴스를 가지고 있지 않다면, Factory를 통해 ViewModel인스턴스를 생성한다.

5. 생성한 ViewModel 인스턴스를 ViewModeStore에 저장하고 만들어진 ViewModel 인스턴스를 클라이언트에게 반환한다.

6. 똑같은 ViewModel 인스턴스 요청이 들어온다면, 1~3번의 과정을 반복하게 된다.

 

 

 

Android Architecture Components Basic Sample

 

 

 

1. 파라미터가 없는 ViewModel - Lifecycle Extensions

     androidx.lifecycle lifecycle-extensions 모듈을 가져와 사용하면 됩니다. 먼저, module 수준의 build.gradle 에 다음과 같이 디펜던시를 추가해줍니다.

      noParamViewModel = ViewModelProvider(this).get(NoParamViewModel::class.java)

 

2. 파라미터가 없는 ViewModel - ViewModelProvider.NewInstanceFactory

 이번에 살펴볼 방법은 NewInstanceFactory 입니다.

  이는 안드로이드가 기본적으로 제공해주는 팩토리 클래스이며, ViewModelProvider.Factory 인터페이스를 구현하고 있습니다. 따라서 ViewModel 클래스가 파라미터를 필요로 하지 않거나, 특별히 팩토리를 커스텀 할 필요가 없는 상황에서는 1번 방법을 사용하거나, 2번 방법을 사용하면 되겠습니다.

 

        noParamViewModel = ViewModelProvider(this, ViewModelProvider.NewInstanceFactory())

            .get(NoParamViewModel::class.java)

 

3. 파라미터가 없는 ViewModel - ViewModelProvider.Factory

    이번에는 직접 ViewModelProvider.Factory 인터페이스를 구현하여 보도록 하겠습니다. 이 방법의 장점은 하나의 팩토리로 다양한 ViewModel 클래스를 관리할 수도 있고, 원치 않는 상황에 대해서 컨트롤 할 수 있습니다.

    class NoParamViewModelFactory : ViewModelProvider.Factory {

        override fun <T : ViewModel?> create(modelClass: Class<T>): T {

            return if (modelClass.isAssignableFrom(NoParamViewModel::class.java)) {

                NoParamViewModel() as T

            } else {

                throw IllegalArgumentException()

            }

        }

    }

 

4. 파라미터가 있는 ViewModel - ViewModelProvider.Factory

    3번 방법의 연장선상에서, ViewModelProvider.Factory 를 구현하면 파라미터를 소유하고 있는 ViewModel 객체의 인스턴스를 생성할 수 있습니다. 직접 구현한 Factory 클래스에 파라미터를 넘겨주어 create() 내에서 인스턴스를 생성할 때 활용하면 됩니다.

 

    class HasParamViewModel(val param: String) : ViewModel()

 

    class HasParamViewModelFactory(private val param: String) : ViewModelProvider.Factory {

        override fun <T : ViewModel?> create(modelClass: Class<T>): T {

            return if (modelClass.isAssignableFrom(HasParamViewModel::class.java)) {

                HasParamViewModel(param) as T

            } else {

                throw IllegalArgumentException()

            }

        }

    }

 

        hasParamViewModel = ViewModelProvider(this, HasParamViewModelFactory(sampleParam))

            .get(HasParamViewModel::class.java)

 

 

5. 파라미터가 없는 AndroidViewModel - AndroidViewModelFactory

    권장하지 않음. 정말 불가피하게 필요한 경우 ViewModel 에서 Context 를 사용해야할 필요성이 있을 때는 AndroidViewModel 클래스를 사용하면 됩니다.

 

    class NoParamAndroidViewModel(application: Application) : AndroidViewModel(application)

 

 

        noParamAndroidViewModel = ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory(application)) .get(NoParamAndroidViewModel::class.java)

 

 

6. 파라미터가 있는 AndroidViewModel

class HasParamAndroidViewModel(application: Application, val param: String)

    : AndroidViewModel(application)

 

 

class HasParamAndroidViewModelFactory(private val application: Application, private val param: String)

    : ViewModelProvider.NewInstanceFactory() {

 

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {

        if (AndroidViewModel::class.java.isAssignableFrom(modelClass)) {

            try {

                return modelClass.getConstructor(Application::class.java, String::class.java)

                    .newInstance(application, param)

            } catch (e: NoSuchMethodException) {

                throw RuntimeException("Cannot create an instance of $modelClass", e)

            } catch (e: IllegalAccessException) {

                throw RuntimeException("Cannot create an instance of $modelClass", e)

            } catch (e: InstantiationException) {

                throw RuntimeException("Cannot create an instance of $modelClass", e)

            } catch (e: InvocationTargetException) {

                throw RuntimeException("Cannot create an instance of $modelClass", e)

            }

        }

        return super.create(modelClass)

    }

}

'til' 카테고리의 다른 글

day26  (0) 2022.01.18
day25  (0) 2022.01.14
day23  (0) 2022.01.13
day22  (0) 2022.01.12
day21  (0) 2022.01.10