일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
- SPI
- DynamicProgramming
- synergy
- Dialog
- 쌓기게임
- 제곱근
- stack
- MFC
- darkmode
- 코인거스름돈
- Collection
- FirebaseAuth
- Java
- QoS
- Dokka
- 동적프로그래밍
- devicedriver
- LRU
- android
- DataStructure
- 피보나치
- 피요모리2
- AfxMessageBox
- Kotlin
- 형변환
- memory
- 리틀포레스트
- WebView
- math
- 보늬밤
- Today
- Total
퉁탕퉁탕 만들어보자
ViewModel 본문
1.ViewModel?
ViewModel을 사용하는 가장 큰 이유는 아무래도 UI삭제 또는 구성 변경 시 데이터 유지를 위함이다.
onSaveInstanceState()에서 간단한 bundle을 통한 UI복구는 가능하지만, 큰 데이터의 경우에는 부적합하기 때문에 ViewModel을 쓰는것이 용이하다.
또 다른 이유로는 Activity나 Framework 내부에서 모든 비지니스 로직을 처리하게되면 안그래도 LifeCycle관련되서 굉장히 많은 로직을 처리하게 되는데 너무 클래스가 커지고, TC작성에도 어려움이 있다. (android framework에 디펜던시가 많아서 mock을 전부 하기에 손이 많이감)
따라서 이때 데이터를 load하는 부분과 비지니스 로직부분을 ViewModel로 위임하면 SRP에도 도움이 되고, 동시에 TC작성에도 용이하다.
ViewModel과 Activity의 관계를 보면,
Activity가 ViewModel의 인스턴스를 갖고있게 하고, ViewModel쪽에서 LiveData를 갖고 Activity에서 ViewModel의 LiveData를 observe하는 식의 구조로 구현을 하게된다.
class MyViewModel : ViewModel() {
// 뷰모델 안에 data인스턴트를 저장한다.
private val users: MutableLiveData<List<User>> by lazy {
MutableLiveData<List<User>>().also {
loadUsers()
}
}
// user list LiveData에 대한 getter 함수를 만들어서 가져갈수있게 한다.
fun getUsers(): LiveData<List<User>> {
return users
}
private fun loadUsers() {
// user를 async하게 땡겨온다.
}
}
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// onCreate가 처음 불릴 때 ViewModel이 생성된다.
// 재생성된 activity는 처음에 생성된 viewmodel과 같은 instance를 받게된다.
// 뷰모델 생성
val model: MyViewModel = ViewModelProvider(this).get(ScoreViewModel::class.java);
model.getUsers().observe(this, Observer<List<User>>{ users ->
// user List를 가지고 UI를 업데이트 한다.
})
}
}
2. LifeCycle
뷰모델은 설계상 Activity보다 오래 생존하게 된다. ViewModel이 생성될 때 연결되는 Activity의 LifeCycle과 연결되며, Activity가 완전히 finish 되면 사라진다. 이때 onCleared()를 Override해서 적절하게 data가 해제될수있도록 한다.
3. ViewModel에서의 Context 사용
ViewModel에서는 Activity Context 객체에 대한 reference를 가지면 안된다. 이유는 ViewModel 설계상 Activity가 여러번 finish되어도 메모리상에 남아있게 되는데, 이때 viewModel이 Activity에 대한 reference를 갖고있게 되면 GC가 collect를 하지못하고 계속 삭제된 Activity가 Memory에 남아있게 되기 때문이다.
하지만 코드를 짜다보면 ViewModel안에서 system service나 각종 data 저장을 위한 sharedPreference를 사용한다던지 하기 위해서 Context가 필요한 경우가 많은데, 이 경우에는 Application Context를 사용해야한다. Activity Context는 Activity의 Lifecycle과 연결이 되어있고, Application Context 같은 경우에는 Application 전체의 Lifecycle과 연결되어있기 때문에 LifeCycle이 다르다. Application Context를 사용을 하기위해서는 일반 ViewModel이 아닌 AndroidViewModel을 extend해서 사용을 하면 된다.
4. ViewModel을 생성하는 여러가지 방법
ViewModel은 일반 객체처럼 new ViewModel() 하고 생성을 하지 않는다.
1) ViewModelProvider사용
var viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
2) Factory사용
var viewModel = ViewModelProvider(this, ViewModelProvider.NewInstanceFactory())
.get(MyViewModel::class.java)
3) ViewModel 생성 시 인수를 주고싶을 때
// 뷰모델 팩토리를 직접 구현
class CalendarViewModelFactory(private val eventDao: PeriodDao, private val pillDao: PillDao) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(CalendarViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return CalendarViewModel(eventDao, pillDao) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
// Activity 에서 내가 구현한 Custom Factory를 사용해서 생성한다.
private val calendarViewModel: CalendarViewModel by viewModels {
CalendarViewModelFactory(
(activity?.application as PillAndPeriodApplication).periodDatabase.periodDao(),
(activity?.application as PillAndPeriodApplication).pillDatabase.pillDao())
}
*주의 ViewModelProviders는 deprecated되었음
(참고: https://developer.android.com/reference/android/arch/lifecycle/ViewModelProviders)
출처: https://medium.com/androiddevelopers/viewmodels-a-simple-example-ed5ac416317e,
디벨로퍼사이트
https://readystory.tistory.com/176
'Computer > Android' 카테고리의 다른 글
Android View LifeCycle (0) | 2022.05.07 |
---|---|
Android RecyclerView (0) | 2022.05.05 |
Android Process And Thread (0) | 2022.04.24 |
Content Provider, Content Resolver, Content Observer (0) | 2022.04.23 |
그래서 Android에서 메모리 관리 어떻게 해? (0) | 2022.04.18 |