(kotlin) MVVM pattern

박용석·2023년 9월 15일
0
  • MVVM(Model-View-ViewModel)

    UI 및 비 UI 코드를 분리하기 위한 UI 아키텍처 디자인 패턴이다. 데이터 바인딩 인프라는 UI 및 연결된 데이터를 동기화된 상태로 유지하고, 사용자 입력을 적절한 명령으로 라우팅하는 느슨한 결합을 제공한다.

  • MVVM의 이점

    반복적인 예비 코딩 스타일 사용. 격리되는 변경 내용은 위험이 적고 실험하기가 더 쉽다.
    단위 테스트 간소화. 서로 격리된 코드 단위는 프로덕션 환경 외부에서 개별적으로 테스트할 수 있다.
    팀 공동 작업 지원. 잘 디자인된 인터페이스를 따르는 분리된 코드는 별도의 개인이나 팀에서 개발한 후 나중에 통합할 수 있다.
    유지 관리 효율성 향상. 분리된 코드의 버그를 수정하면 다른 코드에서 재발할 가능성이 줄어든다.

MVVM 패턴으로 실습을 해보자

ToDo.kt (Model): 할 일을 나타내는 데이터 클래스를 정의한다

data class ToDo(val id: Int, val title: String, val isDone: Boolean)

ToDoRepository.kt (Model): ToDo 항목을 가져오고 저장하는 리포지토리 클래스를 작성한다.

class ToDoRepository {
    private val todoList = mutableListOf<ToDo>()

    init {
        // 초기 데이터 로드 (예: 로컬 DB 또는 API에서 데이터 가져오기
        todoList.add(ToDo(1, "할 일 1", false))
        todoList.add(ToDo(2, "할 일 2", true))
    }

    // ToDo 목록을 반환하는 함수
    fun getAllToDos(): List<ToDo> {
        return todoList
    }

    // 새로운 ToDo를 추가하는 함수
    fun addToDo(todo: ToDo) {
        todoList.add(todo)
    }
}

ToDoViewModel.kt (ViewModel): 비즈니스 로직을 처리하고 View에 데이터를 제공하는 ViewModel 클래스를 작성한다

class ToDoViewModel : ViewModel() {
    private val repository = ToDoRepository()

    // ToDo 목록을 가져오는 함수
    fun getToDoList(): List<ToDo>{
        return repository.getAllToDos()
    }

    // 새로운 ToDo를 추가하는 함수
    fun addNewToDo(todo: ToDo){
        repository.addToDo(todo)
    }
}

MainActivity.kt (View): 사용자 인터페이스와 상호작용하는 화면을 구현한다. ViewBinding을 사용하여 XML 레이아웃과 상호작용한다.

class MainActivity : AppCompatActivity() {
    private lateinit var  viewModel : ToDoViewModel
    private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        viewModel = ViewModelProvider(this).get(ToDoViewModel::class.java)

        val toDoList = viewModel.getToDoList()

        // ToDo 목록을 화면에 표시하는 코드
        val adapter = ToDoAdapter(toDoList)

        // RecyclerView에 LinearLayoutManager 연결
        binding.recyclerView.layoutManager = LinearLayoutManager(this)
        binding.recyclerView.adapter = adapter

        binding.addButton.setOnClickListener {
            val newToDo = ToDo(3, "할 일 3", false)
            viewModel.addNewToDo(newToDo)
            adapter.updateData(viewModel.getToDoList())
        }
    }
}

ToDoAdapter.kt (View): RecyclerView에 할 일 목록을 표시하는 어댑터 클래스를 작성한다.

class ToDoAdapter(private var items: List<ToDo>): RecyclerView.Adapter<ToDoAdapter.ToDoViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ToDoAdapter.ToDoViewHolder {
        val binding = TodoItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return ToDoViewHolder(binding)
    }

    override fun onBindViewHolder(holder: ToDoViewHolder, position: Int) {
        val item = items[position]
        holder.bind(item)
    }

    override fun getItemCount(): Int {
        return items.size
    }

    fun updateData(newItems: List<ToDo>){
        items = newItems
        notifyDataSetChanged()
    }

    inner class ToDoViewHolder(private val binding: TodoItemBinding) : RecyclerView.ViewHolder(binding.root){
        fun bind(todo: ToDo){
            binding.todoTitle.text = todo.title
            binding.isDoneCheckBox.isChecked = todo.isDone

        }
    }
}

현업에서 쓰는 아키텍쳐인 만큼 익숙해질 수 있도록 노력해야겠다.

  • 결과물

profile
슬기로운 개발 활동

0개의 댓글