Android

Android) 새로워진 Mavericks 2.0을 알아보자

가짜 개발자 2021. 9. 22. 19:40


이전에 MvRx에 대한 포스팅을 했습니다.

오늘은 Mavericks 2.0에 대한 내용입니다.

 

 

Mavericks

  • 개별적인 상태 속성을 노출하는 대신, 하나의 불변 데이터 클래스를 사용해 뷰모델을 업데이트하고 UI를 렌더링 합니다.
  • Mavericks 1.0 RxJava 기반으로 되어 있었는데, Mavericks 2.0에서 Coroutines로 새롭게 작성되었습니다.
  • MVI 프레임워크로 상태 관리를 쉽게 처리하기 위해 Airbnb에서 만든 기술입니다.
  • Coroutines, Dagger, Hilt, Jetpack Compose, Jetpack Navigation 등을 지원합니다.

 

What is MVI?

 

 

  • Model - 상태를 나타낸다. MVI에서 Model은 데이터 플로우가 단방향으로 이루어지기 위해 불변성을 보장해야 한다.
  • View - View는 Activity / Fragment를 나타내며, 상태를 전달받아 화면에 렌더링 한다.
  • Intent - 앱 / 사용자가 취하는 행위를 나타내기 위한 의도. View는 Intent를 받고, ViewModel은 Intent를 관찰하여 Model은 그에 따른 새로운 상태로 변환.

 

Add The Dependency

dependencies {
  implementation 'com.airbnb.android:mavericks:x.y.z' // 2.0.0
}

 

Core Concept

  • MavericksState
  • MavericksViewModel
  • MavericksView

 

MavericksState

1. UI를 렌더링 하는데 도움이 되는 모든 속성이 있습니다.

  • Thread Safe
  • Koltin Data Class
  • Immutable Properties
  • 초기 상태를 전달하기 위한 default value를 가지고 있습니다.
  • state는 Kotlin Data Class이기 때문에, 파생 속성을 만들 수 있습니다.
data class UserState(
    val name: String = "사용자",
    val age: Int = 29,
    val regionName: String = "정릉4동",
    val profileImageUrl: String? = null
) : MavericksState {
    // Derived Properties
    val introduction: String
        get() = "이름:$name, 나이:$age, 사는곳:$regionName"
}

 

 

MavericksViewModel

1. 상태 업데이트

2. 다른 클래스들이 관찰할 수 있는 상태 스트림 노출

  • MavericksViewModel은 화면 회전, LMK 등의 Configuration Changes가 발생할 때, 데이터를 유지하기 위해서 Jetpack ViewModel을 구현하는 형태로 되어 있습니다.
  • 일반적인 ViewModel은 내부에 LiveData, MutableLiveData를 생성하고 이를 framgent/activity에 보여주는 방식인 반면, MavericksViewModel은 하나의 Immutable Data Class(state class)를 가지고, 하나의 data class만 업데이트하고 UI를 렌더링 합니다.
  • StateFlow를 사용해서 stream으로 상태를 구독할 수 있는 메서드 제공
  • 상태는 기본적으로 Immutable이라 직접 변경할 수 없습니다. 대신 setState 함수를 사용하여 상태를 업데이트합니다.
  • Kotlin Data Class에서 제공하는 copy() 메서드를 사용하여 속성을 업데이트합니다.
class UserViewModel(initialState: UserState) : 
MavericksViewModel<UserState>(initialState) {
    fun getIntroduction() = setState { 
    	copy(name = "이름:$name, 나이:$age, 사는곳:$regionName") 
    }
}

 

MavericksView

  • MavericksView는 실제로 데이터를 렌더링 하는 곳입니다.

 

1. ViewModel delegates를 통해 MavericksViewModel에 접근할 수 있습니다. 

2. invalidate() 메서드를 Override합니다. 상태 변경 시 UI를 다시 그리는데 사용됩니다.

 

  • withState() 메소드를 사용해 state observer를 구현하고, 이를 기반으로 UI를 업데이트합니다.
  • withState() 메서드는 단일 ViewModel에서 ViewModel의 상태에 동기적으로 접근하고 block의 결과를 반환합니다.
class UserFragment : Fragment(R.layout.fragment_user), MavericksView {

    private lateinit var binding: FragmentUserBinding
    private val viewModel: UserViewModel by fragmentViewModel()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding = FragmentUserBinding.bind(view)

        binding.imageProfile.setOnClickListener {
            viewModel.getIntroduction()
        }
    }

    override fun invalidate() = withState(viewModel) { state ->
        // Update your views with the latest state here.
        // This will get called any time your state changes and the viewLifecycleOwner is STARTED.
        with(binding) {
            textName.text = state.name
            textAge.text = state.age.toString()
            textRegion.text = state.regionName
        }
    }
}

 

※ Application 클래스를 만들고 Mavericks를 초기화해줘야 합니다. 

  • 초기화해주지 않으면 IllegalStateException이 발생합니다.
class UserApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        Mavericks.initialize(this)
    }
}

// AndroidManifest.xml
<application
        android:name=".UserApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name">

Preferences

airbnb mavericks

Introducing Mavericks

Maverics Architecture

Mavericks

반응형