본문 바로가기

나의 플랫폼/안드로이드

[Android][DI] ViewModel onCleared 함수가 호출 되지 않을 때

Android Architecture Component 라이브러리에서 제공하는 ViewModel 클래스에서 onCleared라는 함수를 override 할 수 있습니다.

이 함수에서 ViewModel이 라이프사이클에서 종료가 되었을 때 호출 되어 불필요한 메모리를 초기화 시킵니다.
(CompositeDisposable를 정의하여 onCleared 함수에서 clear를 시키기도 하죠.)

그런데 이상하게 ViewModel을 생성한 Activity나 Fragment를 종료 시켰는데 onCleared 함수가 호출이 되지 않을 때가 있다.

그럼 아래 두 가지를 테스트 해봐라.

 

1. Android Support 라이브러리 버전 확인

 Android Support 라이브러리 버전이 27.1.0 이하일 경우 onCleared가 Fragment 에서 호출이 되지 않는 다는 이슈가 있다.
버전을 27.1.1 이상으로 올려봐라. (28.0.0-rc1에서 정상 수정이 되었다는 내용도 있음)

https://stackoverflow.com/a/49411448

 

2. ViewModel 생성 Scope

 아마  onCleared 함수가 호출이 되지 않은 경우는 DI(Dependency Injection)을 사용하시는 분들이 제법 경험할 듯 하다. (나 또한 그랬음...)
ViewModel의 라이프사이클은 아래 그림처럼 되어 있다.

Scope가 Activity 일 경우

만약, DI를 할 때 Scope를 Activity나 Fragment로 지정하지 않았을 경우 앱이 종료 될때까지 onCleared함수가 호출되는 것을 볼 수 없을 것이다.

 

따라서, 사용하는 DI에 Scope를 지정하면 되지만... 만약 그게 어려우신 분들안 아래와 같이 ViewModelProviders를 이용 하세요.

//inside of fragment onCreate()

//scoped to fragment
viewModel = ViewModelProviders.of(this).get(SharedViewModel::class.java)

//scoped to activity
viewModel = ViewModelProviders.of(requireActivity()).get(SharedViewModel::class.java)

https://stackoverflow.com/a/54801824

 

Shared ViewModel's onCleared() is never called

I have a single Activity application. In one part of the app there is a master-detail combination of Fragments that use a shared ViewModel to share some data between them. The problem I face is tha...

stackoverflow.com

이렇게 ViewModel를 지정하면 각각 Activity마다 Fragment마다 라이프사이클에 따라가게 됩니다.

그래서 OnDestroy와 함께 ViewModel에서 onCleared 함수를 호출하게 되죠.

 

한가지 더 첨부하자면, 호출 시 ViewModelProvider.Factory를  of함수에서 두번째 파라미터로 넣을 수 있는데요.
아래와 같습니다.


class PostListActivity : AppCompatActivity() {

    @Inject
    lateinit var viewModelFactory: ViewModelProvider.Factory

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_post_list)
        getAppInjector().inject(this)
        val vm = ViewModelProviders.of(this, viewModelFactory)[PostListViewModel::class.java]
        vm.posts.observe(this, Observer(::updatePosts))
    }
    
    //...
}

https://proandroiddev.com/viewmodel-with-dagger2-architecture-components-2e06f06c9455

 

ViewModel with Dagger2 (Android Architecture Components)

Hello everyone! 👋 In this story I want to share some light on how you can use ViewModel (Android Architecture Components) with Dagger 2…

proandroiddev.com

ViewModelFactory를 커스텀하게 만드실 분들은 위와 같이 추가하시면 됩니다.

참고하세요.