- Today
- Total
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Java
- DataBinding
- 삼성역량테스트
- 투포인터
- 비트마스킹
- 아키텍처패턴
- Kotlin
- MVVM
- 탐탁노트북파우치
- 삼성파우치
- 코틀린
- 자바
- 등산로조성
- 코딩테스트
- 싸피
- kotiln
- 알고리즘
- 탐탁삼성파우치
- ssafy서울
- 안드로이드#코틀린#디자인패턴#싱글턴패턴#개발#앱개발
- 백준
- Higher-Order
- 삼성청년sw아카데미
- lateinit
- bitmasking
- nullalble
- 안드로이드
- #충무로맛집#골목식당#스테이크#
- Android
- tomtoc
공상하는 개발자
[아키텍쳐 패턴] 3탄 : MVVM 패턴 적용하기. 본문
2탄 MVP 패턴을 포스팅 한 이후 오랜 시간이 흘렀다..
그동안 MVVM에 대한 공부를 하고,
프로젝트에 적용하면서 조금은 익숙해진 것 같아 포스팅을 하려고 한다.
언제나 날카로운 피드백은 환영이다.
드루와
...
MVVM (Model + View + ViewModel)
정의
-> 모델 + 뷰 + 뷰모델의 구조이다. MVP 패턴에서 프레젠터가 뷰모델로 바뀐 것으로, 뷰와 프레젠터의 의존성을 없앨 수 있는 패턴이다.
Model : 프로그램에서 사용되는 실제 데이터 및 데이터 로직을 처리하는 부분.
ex) retrofit을 필요한 데이터를 받아오는 것.
iew : 사용자의 입력을 받고, 보여주는 부분.
MVVM의 핵심!
ViewModel은 View를 알지 못하고, View는 Model을 알지 못하지만 ViewModel은 안다. 그렇기에 View는 ViewModel을 계속해서 observe 하다가 변화가 생기면 UI 로직에 의해 출력을 발생시킨다. (oberver pattern 이용)
Databinding
- View와 ViewModel을 독립시켜줌.
- ViewModel의 LiveData를 계속해서 관찰해서 변화가 생기면 로직을 통해 xml에서 편하게 바꿔줄 수 있다.
- LifeCycleOwner 가 필요하다.
VisitedPlaceActivity.kt
class VisitedPlaceActivity : AppCompatActivity() {
lateinit var placeAdapter: PlaceAdapter
val vm: VisitedPlaceViewModel = VisitedPlaceViewModel()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: ActivityVisitedPlaceBinding =
DataBindingUtil.setContentView(this, R.layout.activity_visited_place)
binding.vm = vm
binding.lifecycleOwner = this
placeAdapter = PlaceAdapter()
binding.actSearchRv.adapter = placeAdapter
binding.btnSearch.setOnClickListener {
vm.getAddress(binding.actSearchEtSearch.text.toString())
}
}
}
1. search 버튼을 누르게 되면 VisitedPlaceViewModel의 getAddress 함수를 부르게 된다. ( View에서 ViewModel을 부름.)
VisitedPlaceViewModel.kt
class VisitedPlaceViewModel : ViewModel() {
private val addressRepository: AddressRepository = AddressRepository()
private val disposables = CompositeDisposable()
val PlaceList = MutableLiveData<List<Place>>()
fun getAddress(search: String) {
disposables.add(addressRepository.getAddress(search) //RxJava 이용
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe {
}
.doOnTerminate {}
.subscribe { // 구현 로직
PlaceList.value = it.message //Place를 담은 리스트를 PlaceList에 넣어준다.
}
)
}
}
2. getAddress가 View로부터 불려지면 RxJava를 이용해 로직을 실행시켜준다.
(RxJava의 정보가 궁금하다면 밑의 링크에 들어가 보길 추천한다.)
activity_visited_place.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"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="vm"
type="com.example.earlybuddy_pattern.ui.visited.VisitedPlaceViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.search.SearchActivity">
/*
...
*/
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/act_search_rv"
setPlaceData="@{vm.placeList}" // ViewModel의 placeList가 들어오는 부분.
android:layout_width="match_parent"
android:layout_height="0dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/act_search_cl_search" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
3. 2번에서 PlaceList의 값이 갱신되면 xml에 DataBinding으로 연결된 부분이 갱신된다. 위의 경우에는 setPlaceData라는 BindingAdapter로 RecyclerView에 데이터를 넣어주고 있다.
BindingAdapter.kt
@BindingAdapter("setPlaceData")
fun RecyclerView.setData(placeData: List<Any>?) {
when (placeData) {
null -> {
}
else -> {
if (placeData.isNotEmpty()) {
(this.adapter as PlaceAdapter).setListData(placeData as List<Place>)
// setListData는 리사이클러뷰에 데이터를 넣어주는 메소드.
}
}
}
}
4. setPlaceData의 형태는 위와 같다.
결과
결론
위와 같이 로직을 분리하여 유지보수를 편하게 하는 것이 아키텍처 패턴을 쓰는 이유이다. 웬만한 아키텍처 패턴은 얼추 익힌 거 같으니 프로젝트에 적용을 시켜볼까...(얼리 버디 파이팅...!)
'개발 > 안드로이드' 카테고리의 다른 글
[안드로이드] 서버에 form data 로 데이터 전송하기.(MultiPart) (4) | 2020.07.14 |
---|---|
[기초 탄탄] 안드로이드 스레드 파헤치기. (0) | 2020.06.14 |
[Android/kotlin] DataBinding 파헤치기 (0) | 2020.02.09 |
[Kotlin] Higher-Order Functions 이란? (0) | 2020.02.02 |
[Kotlin] Null 안정성 파헤치기 (0) | 2020.01.25 |