-
간단한 MVVM 패턴 예제안드로이드 학습/Android 기술면접 대비 코드 2023. 6. 7. 21:23
기본적으로 MVC나 MVP 패턴 같은 의존성을 없애기 위해 Databinding을 적용 시켰고 LiveData도 적용시켰습니다.
삼국지 영웅 뽑기를 주제로 선정!
1.build.gradle
android { ... 생략 ... buildFeatures { dataBinding = true } }
- 먼저 build.gradle 파일에 dataBinding을 사용하겠다는 선언 추가
2. Character.kt
data class Character(var name: String, var strength: Int, var intelligence: Int)
- 삼국지 인물의 이름, 무력, 지력을 넣은 data class.
- 'data class' 로 지정해주면 알아서 getter setter method 지원!!!
3. Model.kt
class Model { private val characterList = mutableListOf<Character>() private lateinit var character: Character init { fillCharacter() } private fun fillCharacter() { characterList.add(Character("유비", 80, 80)) characterList.add(Character("조조", 85, 95)) characterList.add(Character("손권", 70, 75)) characterList.add(Character("제갈량", 30, 100)) characterList.add(Character("여포", 100, 30)) } fun getRandomCharacter(): Character { character = characterList[(Math.random() * 5).toInt()] return character } }
- fillCharacter에서 5명의 인물만 미리 넣어놓음
- getRandomCharacter는 랜덤하게 5명의 인물중 하나만 선택할 예정. ViewModel에서 사용될 예정.
4. ViewModel.kt
class MainViewModel : ViewModel() { private var model: Model = Model() private var _character = MutableLiveData<Character>() val character: LiveData<Character> get() = _character fun getRandomCharacter() { _character.value = model.getRandomCharacter() } fun isShow(str: String?): Boolean { return str != null && str != "0" } }
- getRandomCharacter()는 model에서 랜덤하게 인물을 정하는 부분 가져옴
- isShow는 xml파일에서 visible을 세팅하기 위해 만들어준 부분. 왜냐하면 맨 처음에는 정보가 없으면 TextView가 안보여지게 하려고 Visible 세팅
5. MainActivity.kt
class MainActivity : AppCompatActivity() { lateinit var binding: ActivityMainBinding var mainViewModel = MainViewModel() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = DataBindingUtil.setContentView(this, R.layout.activity_main) binding.apply { // **중요** binding에 LifeCycleOwner을 지정해줘야 LiveData가 실시간으로 변화 lifecycleOwner = this@MainActivity // xml 파일에 선언한 viewModel viewModel = mainViewModel } } fun getRandomCharacter() { mainViewModel.getRandomCharacter() } }
- 데이터 바인딩을 사용하기 위해 아래 2줄 추가
lateinit var binding: ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
- 실시간 데이터 변화를 위해 'lifecycleOwner'와 'viewModel' 지정
- 'viewModel' 같은 경우 xml에서 variable로 지정될 것을 연결 시켜주는 것이다.
binding.apply { // **중요** binding에 LifeCycleOwner을 지정해줘야 LiveData가 실시간으로 변화 lifecycleOwner = this@MainActivity // xml 파일에 선언한 viewModel viewModel = mainViewModel }
6. activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <import type="android.view.View" /> <variable name="viewModel" type="w2022v9o12.simple.simplemvvm.viewmodel.MainViewModel" /> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:id="@+id/characterInfoLayout" android:layout_width="match_parent" android:layout_height="0dp" android:layout_marginBottom="100dp" android:gravity="center" android:orientation="vertical" app:layout_constraintBottom_toTopOf="@+id/plusBtn" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> <TextView android:id="@+id/charName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{viewModel.character.name!=null ? `이름 : ` + viewModel.character.name : `영웅을 뽑아주세요.`}" android:textColor="@color/black" android:textSize="20dp"/> <TextView android:id="@+id/strength" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="@{`무력 :` + String.valueOf(viewModel.character.strength), default=``}" android:textColor="@color/black" android:textSize="20dp" android:visibility="@{viewModel.isShow(String.valueOf(viewModel.character.strength)) ? View.VISIBLE : View.GONE , default=gone}" /> <TextView android:id="@+id/intelligence" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="@{`지력 :` + String.valueOf(viewModel.character.intelligence), default=``}" android:textColor="@color/black" android:textSize="20dp" android:visibility="@{viewModel.isShow(String.valueOf(viewModel.character.intelligence)) ? View.VISIBLE : View.GONE , default=gone}" /> </LinearLayout> <Button android:id="@+id/plusBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="150dp" android:onClick="@{() -> viewModel.getRandomCharacter()}" android:text="삼국지 영웅 뽑기" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
- databinding을 위해 layout 태그로 감싸기
- View.VISIBLE을 사용하기 위해 임포트
<import type="android.view.View" />
- 만들어진 viewModel을 xml에 가져오기
<variable name="viewModel" type="w2022v9o12.simple.simplemvvm.viewmodel.MainViewModel" />
- textview에 Visible을 적용시키기 위해 조건부 연산자(? : )를 사용
- viewModel에서 만든 'getRandomCharacter()'와 button 연동
android:onClick="@{() -> viewModel.getRandomCharacter()}"
최종 결과 보기 :
간단히 mvvm + databinding + livedata 예제를 만들어 보았다.
데이터 바인딩과 livedata를 공부하긴 했었지만 예제를 만들어 본것이 아니어서 한참 헤맸다.
이참에 그냥 databinding과 livedata도 예제로 따로 만들어 보아야겠다.
'안드로이드 학습 > Android 기술면접 대비 코드' 카테고리의 다른 글
MVC 패턴 예제 (0) 2023.12.14 안드로이드 Bound Service 예제 (0) 2023.07.03 MVVM 패턴 + databinding + Room DB + recyclerview 예제 (0) 2023.06.15 (AAC) Room DB (0) 2023.06.14 Broadcast Receiver 예제 (0) 2023.06.11