Android ViewModel: 수동 의존 주입이 간단해짐

15459 단어 androidtutorialkotlin
모델 의존항 주입을 쉽게 볼 수 있는 라이브러리에 직접 방문하려면 Lazy ViewModelsmy GitHub를 보십시오
안드로이드팀은 갈수록 지원Dependency InjectionDagger 프레임워크를 지원하고 심지어 개발Hilt--그들이 Dagger에 구축한 안드로이드 DI 프레임워크를 현대 안드로이드 개발에 사용하도록 추천하고 있다.
그들의 안내서manual dependency injection에서 안드로이드팀은 보기 모델의 수동 DI 방법을 열거했다.그것들은 수동 DI의 기본 방법onCreate에서 필요한 모든 내용을 실례화하고 사용하기lateinit var 보기 모델), 모든 활동 간의 의존 관계를 사용자 정의AppContainer로 처리하는 용기 방법을 제공한다.
그들이 내놓은 또 다른 선택은 비수나 칼자루로 이 과정을 처리하는 것을 권장하는 것이다.그러나 많은 응용 프로그램에서 DI 프레임워크를 도입하는 비용은 필요하지 않다.반대로 모든 보일러판이 없는 상황에서 의존항을 안드로이드 활동과 세션 보기 모델에 수동으로 주입할 수 있는 방법이 있다면?

Android Lifecycle ViewModel Extensions를 사용한 불활성 DI
Android Fragment &Lifecycle 팀이 보기 모델을 활동과 세션에서 사용하기 쉽게 하려는 방법 중 하나는 라이브러리 제공Android Lifecycle ViewModel Kotlin Extensions이다.
dependencies { 
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
}
이 라이브러리는 위탁 방법을 사용하여 세션이나 이벤트에서 실례화된 보기 모델을 만들 수 있으며 범위가 적당한 보기 모델을 쉽게 만들 수 있습니다.
class MyActivity : AppCompatActivity() {

    private val model: MyViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        model.getUsers().observe(this, Observer<List<User>>{ users ->
            // update UI
        })
    }
}
이거 정말 예뻐요!그러나 만약에 우리의 보기 모델이 repository를 사용하여 Retrofit을 호출해야 한다면 어떻게 해야 합니까?우리는 보기 모델을 구축할 때 이 저장소를 보기 모델에 주입하기를 희망한다.

모델 제공 프로그램 플랜트 보기
이 동작을 사용하는 방법은 ViewModelProvider.Factory 를 사용합니다. 이 동작을 사용하면 필요한 의존항이 있는 보기 모델을 실례화할 수 있습니다.이를 위해, 인터페이스를 확장하거나, 덮어쓰기 ViewModelProvider.Factory 방법의 object 를 되돌려 주는 함수를 만들어야 합니다.
여기서 멈추려면 Kotlin 함수를 생성하여 작업을 완료할 수 있습니다.
fun createWithFactory(
  create: () -> ViewModel
  ): ViewModelProvider.Factory {
    return object : ViewModelProvider.Factory {
        override fun <T : ViewModel?> create(modelClass: Class<T>): T {
            @Suppress("UNCHECKED_CAST")// Casting T as ViewModel
            return create.invoke() as T
        }
    }
}
다음과 같은 활동 또는 세션에서 사용합니다.
private val model: MyViewModel by lazy {
  ViewModelProvider(
    this, 
    createWithFactory {
        MyViewModel(repo = MyRepository())
    }
  ).get(MyViewModel::class.java)
}
우리는 이제 필요한 의존항을 가진 보기 모델을 만들 수 있습니다.그러나 우리 공장이 하나의 기능으로 추상화되어도 우리는 Factory.create의 보일러판을 관리해야 한다.

뷰 모델 공급자 및 Kotlin 확장Mashup
보기 모형을 만들기 위해 ViewModelProvider 또는 by viewModels를 사용할 수 있지만 공장이 없으면 필요한 의존항을 주입할 수 없다는 것을 기억하십시오.
현재 우리는 공장 실례화 보기 모형을 사용하는 간편한 방법이 생겼다. 우리는 이 보기 모형의 Kotlin을 확장해서 이 by activityViewModels 보일러판을 숨길 수 있다.다음은 세션의 외관입니다.
private val model: MyViewModel by activityViewModels {
    createWithFactory {
        MyViewModel(repo = MyRepository())
    }
}
거의 완벽하다.우리가 해야 할 일은 공장과 lambda를 제공하여 우리의 보기 모형을 되돌려 주는 것이다.그러나 ViewModelProvider 라이브러리와 Kotlin 확장 함수의 도움으로 우리는 더욱 진일보할 수 있다.

끝: 손쉬운 모델 보기 DI
확장 함수의 강력한 기능, 공장 지식과 lifecycle-viewmodel-ktx류를 이용하여 보기 모델의 창설을 활동과 부분에 의뢰하는 함수입니다.
보기 모형을 lambda로 만들고 되돌아오는 형식 ViewModelLazy, 나머지 부분은 <VM : ViewModel>viewModelBuilder 확장으로 완성하는 함수를 제공합니다.
/**
 * Get a [ViewModel] in an [ComponentActivity].
 */
@MainThread
inline fun <reified VM : ViewModel> ComponentActivity.viewModelBuilder(
    noinline viewModelInitializer: () -> VM
): Lazy<VM> {
    return ViewModelLazy(
        viewModelClass = VM::class,
        storeProducer = { viewModelStore },
        factoryProducer = {
            return@ViewModelLazy object : ViewModelProvider.Factory {
                override fun <T : ViewModel?> create(modelClass: Class<T>): T {
                    @Suppress("UNCHECKED_CAST")// Casting T as ViewModel
                    return viewModelInitializer.invoke() as T
                }
            }
        }
    )
}

/**
 * Get a [ViewModel] in a [Fragment].
 */
@MainThread
inline fun <reified VM : ViewModel> Fragment.activityViewModelBuilder(
    noinline viewModelInitializer: () -> VM
): Lazy<VM> {
    return ViewModelLazy(
        viewModelClass = VM::class,
        storeProducer = { requireActivity().viewModelStore },
        factoryProducer = {
            object : ViewModelProvider.Factory {
                override fun <T : ViewModel?> create(modelClass: Class<T>): T {
                    @Suppress("UNCHECKED_CAST")// Casting T as ViewModel
                    return viewModelInitializer.invoke() as T
                }
            }
        }
    )
}
현재 우리의 활동 중:
private val model: MyViewModel by viewModelBuilder {
    MyViewModel(repo = MyRepository())  
}
또는 세션:
private val model: MyViewModel by activityViewModelBuilder {
    MyViewModel(repo = MyRepository())  
}
우리는 번거로운 템플릿 파일 없이 ViewModel과 필요한 모든 의존 항목을 쉽게 구축할 수 있습니다.
복잡한 안드로이드 보기 모델이 필요하다면, 신뢰할 수 있는 의존 주입 원칙을 따르고, 완전한 의존 주입 프레임워크의 복잡성을 적용할 준비가 되어 있지 않다면, 이 옵션을 제공하여 작업을 더욱 쉽게 관리할 수 있기를 바랍니다.
만약 안드로이드 뷰 모델에 대해 어떤 생각을 가지고 있거나 수동 DI 방법을 공유하고 싶다면 망설이지 말고 트위터에 연락하거나 따라와 이 이야기에 대해 논평해 주세요.
이 이야기는 최초로 나의 블로그ajkueterman.dev에 발표되었다.

좋은 웹페이지 즐겨찾기