Android

디자인 아키텍처 1 - MVVM

c0de_h0ng 2021. 11. 15. 22:52
728x90

MVVM이란?

MVVM이란 MVC 패턴 특성상 Activity에 모든 코드를 다 집어넣으면서 Activity가 무거워지고 View와 Model 간의 의존성이 높아지며 앱 규모가 커질수록 코드가 복잡해지는 단점을 보완하고자 나온 패턴이다.

MVVM은 Model, View, ViewModel로 구성되어 있다.

MVVM

View

  • Activity/Fragment
  • 비지니스 로직을 포함하지 않고 UI와 관련된 로직만 존재
  • 유저의 Action을 감지(ex. 버튼 클릭)
  • ViewModel을 Observe 하다가 값이 변경되면 해당 값을 처리

ViewModel

  • View가 요청한 데이터를 Model에 요청
  • Model로부터 요청한 데이터를 받음
  • 비지니스 로직만 존재

Model

  • 실질적인 Data를 다루는 구성 요소
  • ViewModel로부터 데이터를 요청받거나 요청한 데이터를 반환
  • 서버 DB, 로컬 DB, Api를 이용

MVVM 흐름

View -> ViewModel -> Repository -> DataSource(Api, Local DB)

구글 공식 MVVM 구조도

구조도에 따라서 구현

구현에 앞서서 Android AAC에 ViewModel이라고 있는데 이는 엄연히 말하자면 MVVM의 ViewModel과는 다른 것이다. 하지만 구글에서 MVVM을 구현할 때 AAC의 ViewModel을 사용하면 생명주기에 맞는 클래스를 구현할 수 있고 데이터를 유지할 수 있도록 제공하기 때문에 사용한다.

 

예를 들어 A유저가 '내 정보 검색하기'라는 버튼을 클릭한다고 가정해 본다.

  1. Activity에서 A유저의 클릭 이벤트를 감지한다.
  2. RemoteDataSource에서 내 정보 검색하기 Api를 호출한다.
  3. 서버로 부터 받은 A유저 데이터를 ViewModel의 LiveData에 저장한다.
  4. Activity는 LivceData의 변화를 Observe 하여 UI와 데이터 상태를 동기화한다.

예시의 상황을 아래와 같이 구현해 보았다.(참고로 의존성 주입으로  Hilt를 사용)

 

- ApiService

interface ApiService {
    @GET("user")
    suspend fun getUser(id: Long): User
}

 

 

- Repository

class MainRepository @Inject constructor(private val apiService: ApiService) {
    
    suspend fun getUser(id: Long) = withContext(Dispatchers.IO) {
        return@withContext apiService.getUser(id)
    }

}

 

- ViewModel

@HiltViewModel
class MainViewModel @Inject constructor(private val repository: MainRepository) : ViewModel() {

    private val _user = MutableLiveData<User>()
    val user: LiveData<User>
        get() = _user

    fun getUser(id: Long) = viewModelScope.launch {
        _user.value = repository.getUser(id)
    }

}

 

 

- Activity

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    private val viewModel: MainViewModel by viewModels()

    private lateinit var dataBinding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        dataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)

        //유저의 값이 변경될 경우
        viewModel.user.observe(this) {
            Toast.makeText(this, it.name, Toast.LENGTH_SHORT).show()
        }

        dataBinding.searchButton.setOnClickListener {
            viewModel.userApi(3422)
        }

    }
}

 

'Android' 카테고리의 다른 글

이제는 필수가 되어 버린 페이지네이션(Pagination)  (0) 2021.11.17
디자인 아키텍처 3 - MVC  (0) 2021.11.16
Layout xml 그룹 관리  (0) 2021.11.16
디자인 아키텍처 2 - MVP  (0) 2021.11.16
CustomView 1 - 이메일 입력창  (0) 2021.11.16