관련코드 Github주소 바로가기 - https://github.com/puze/AndroidCalendar.git

목표

  • MVC패턴의 이해
  • 뷰바인딩의 사용
  • 리사이클러 뷰의 사용
  • 어댑터 안에서의 바인딩 사용
  • 캘린더 클래스의 사용

MVC 패턴

MVC패턴이란 Model - View - Controller 로 이루어진 디자인 패턴이다.
이러한 패턴을 적용 시킴으로써 다른 사람이 코드를 파악하는 것이 용이하고
유지보수를 쉽게 할수 있게 한다.

  • 모델(Model)
    • 데이터의 집합이라고 볼 수 있다.
    • 데이터의 가공까지 포함한다.
    • 모델에선 뷰와 컨트롤러의 정보를 가지고 있지 않다. (독립적임)
  • 뷰(View)
    • 사용자에게 보여지는 부분을 담당한다.
    • 뷰에선 모델의 정보를 표시하지만 컨트롤러의 정보는 가지고 있지 않다. (모델에 종속적임)
  • 컨트롤러(Controller)
    • 사용자의 입력을 받는다.
    • 화면 뒤에서 모델과 뷰를 연결하는 역할을 한다. (모델과 뷰에 종속적)

독립적 : 어떤(혹은 해당) 클래스가 없어도 작동할 수 있다.
종속적 : 작동하기위해 해당 클래스가 필요하다.

이 디자인 패턴을 이 안드로이드 아키텍처에 적용시키면 어떻게 될까.
나름대로 MVC패턴으로 앞으로 만들 캘린더를 구조화를 시켜보자면

  • 모델 : 액티비티 구성에 필요한 항목의 데이터 -> 뷰 바인딩과 엑티비티에 독립적
  • 뷰 : 메인 액티비티의 뷰 바인딩(애초에 개발자가 구현하지 않음) -> 데이터와 엑티비티에 독립적
  • 컨트롤러 : 메인 액티비티 -> 데이터와 바인딩에 종속적

뷰(바인딩)가 모델에 독립적일 필요는 없지만 위의 대전제는 성립하므로 이런 구조를 생각해볼 수 있겠다.

사실 뷰가 모델에 독립적인 상태로 MVP패턴에 가깝다.
MVC와의 차이는 컨트롤러가 Presenter가 되고 뷰는 모델에 독립적이게된다.

액티비티는 뷰로서만 사용하고 액티비티 컨트롤러 클래스를 따로 작성하는 방법도 있다.

뷰 바인딩

  1. build.gradle 추가
    build.gradle에 다음을 추가한다.
android {
...
    buildFeatures {
        viewBinding = ture
    }
}
  1. 레이아웃 xml 작성
    엑티비티에 올라갈 레이아웃을 작성한다
  2. 뷰 바인딩을 초기화

위의 코드와 같이 lateinit 으로 레이아웃의 binding을 선언한 뒤
onCreate() 에서 binding에 inflate함수로 초기화를 한다.
액티비티의 setContentView는 binding.root를 파라미터로 불러옴으로써 레이아웃 역시 초기화가 가능하다.
이후 binding 변수를 통해 해당 액티비티의 id를 선언한 모든 뷰에 접근이 가능하다.

이전의 방식으로는 findOfViewId(R.id.AAA) 식으로 접근 하거나
잠깐 레이아웃에서 설정한 id에 직접 접근(Kotlin Synthetic)이 가능했었다.
출처 : https://todaycode.tistory.com/29

리사이클러뷰

  • 리스트뷰와 그리드뷰를 대신 할 수 있는 뷰
  • 어댑터를 이용해 뷰를 컨트롤
  • 이름으로부터 알수 있듯이 재활용이 포인트
  • 재활용 하는것은 각 항목(item)
    출처 :https://blog.hexabrain.net/363
  • 리사이클러뷰를 선언한 후 레이아웃 매니저를 통해서 초기화하여 사용한다.
  • 사용가능한 레이아웃은 그리드레이아웃, 리니어 레이아웃, 스태거드 그리드 레이아웃이 있다. "레이아웃 매니저 바로가기"

어댑터

위의 MVC패턴과 유사한 아이디어에서 나온 오브젝트이다.
컨트롤러부분을 담당하기위한 오브젝트이며 뷰에서 데이터의 가공과 로직을 배제하고 어댑터에서 작성한다.
구조는 다음과 같이 되겠다.

또한 리사이클러뷰 어댑터를 구현하는데 있어서 뷰홀더 또한 구현해야한다.
뷰홀더란 리사이클러 뷰에 들어갈 항목의 뷰 및 메타데이터를 뜻한다.

캘린더 구현

  1. 레이아웃 생성
    기본적으로 사용할 메인 액티비티와 리사이클러뷰를 포함한 레이아웃을 준비한다.
  2. 레이아웃 매니저 할당
    다음과 같이 리사이클러뷰의 레이아웃 매니저에 그리드 레이아웃 매니저를 할당한다.
  3. 모델(데이터) 생성
    캘린더 안에 들어갈 아이템의 데이터 클래스를 생성한다.
    우리는 항목에 들어갈 일(day)만 표시할 것 이므로 int형 day하나만 포함한다.
  4. 뷰홀더 구현
    어댑터를 구현하는데 있어서 필요한 뷰홀더도 구현하기로한다.
    현재 구현할 뷰 홀더는 캘린더 어댑터에 종속적이기 때문에
    캘린더 어댑터 클래스안에 inner class(nested class)로 작성한다.
    생성자 파라미터로는 항목에들어갈 레이아웃의 바인딩을 받아와
    init생성자에 해당 항목에 클릭리스너를 달아준다.
    또한 bind메소드를 구현하여 해당 항목이 어떻게 표시될지 작성을한다.
    파라미터로는 앞서 작성했던 모델을 사용하도록 한다.
  5. 어댑터 구현
    리사이클러 뷰의 어댑터를 상속받고 (RecyclerView.Adapter<CalendarAdapter.CalendarViewHolder>())
    오버라이딩이 필요한 메소드는 3개가 있다.
    • onCreateViewHolder : 뷰홀더를 생성할때 호출되며 여기서 생성한 뷰홀더 객체를 반환한다.
    • onBindViewHolder : 뷰홀더를 실제 데이터와 연결한다.
    • getItemCount : 관리해야할 아이템의 크기를 반환한다.
  6. 액티비티 구현
    리사이클러뷰의 구현에 필요한 준비는 끝났고 안에 담을 내용을 구현하자.
    캘린더를 구현하기 위해 Calendar클래스를 이용한다.
    이 클래스를 이용해 직접 구현하고 다루려면 힘든 달력관련 함수들을 손쉽게 다룰수 있다.
    캘린더 작성 알고리즘은 다음과 같다.
    • 캘린더를 현재 달의 1일로 설정한다.
    • 리사이클러 뷰에 들어갈 데이터리스트를 선언한다.
    • 1일이 시작하는 요일을 찾고 월요일부터 해당요일의 차를 빈 데이터로 넣는다.
    • 해당 월의 1일부터 해당 월의 마지막 일까지 넣는다.
    • 작업이 끝난 데이터리스트를 이용하여 어댑터를 생성하고 리사이클러 뷰의 어댑터에 할당한다.캘린더 클래스를 이용하여 현재달 역시 출력 할 수 있다.

확장 가능한 부분

  • 다른 날짜를 선택하여 해당 캘린더를 다시 그리는 기능
  • 액티비티에 종속되있지 않고 어디서나 불러올수 있게 모듈화 구현
  • 뷰홀더에 일 이외에 다른 데이터(메모 혹은 스케줄)도 표시

마치며..

캘린더를 작성하기위해 mvc패턴과 뷰바인더, 리사이클러뷰, 어댑터, 뷰홀더까지 여러 개념들을 소개하였다.
코드는 github(바로가기)에서 확인 가능하다.

+ Recent posts