먼저 어댑터 패턴부터 살펴보자. 아래 그림이 보통 Adapter 패턴을 설명할 때 사용되는 인용되는 그림이다.
위 그림을 간단히 설명하면 Client가 Adapter의 인터페이스의 시그내처만 참고하여 구현을 하면, 상황에 따라 Adaptee에 맞는 Adapter를 사용하는 것만으로 수정 없이 사용이 가능하다는 것이다.
실생활 예로 보면 위의 설명이 더이해가 잘 될 것이다.
하지만 패턴이 실제에서도 적용되기는 쉽지 않다. 안드로이드에서는 Client와 Adapter가 깔끔하게 분리되지 못하고, Adapter-Adaptee 보다 Adapter-Client에게 더 의존성이 많다. CameraBrowser-CameraAdapter나 MenuPopupHelper-MenuAdapter 처럼 말이다. 대신에 의존성이 있는 경우에는 Client 안에 이너클래스로 Adapter를 보통 가지고 있어, 사용할 때 어떤 Client와 Adapter를 사용할 지 혼란스러운 경우는 없을 것이다.
안드로이드에서의 어댑터는 뷰(Client)와 데이터 셋(Adaptee)를 연결해주는 역할을 한다. 어댑터는 데이터 아이템에 접근할 수 있도록 하며, 데이터 셋 속 아이템의 뷰를 그리는 역할도 담당한다.
종류
아래와 같이 크게 3종류의 Adapter들로 나눌 수 있다.
android.widget.Adapter 인터페이스를 상속받은 어댑터들
- SpinnerAdapter
- ListAdapter
android.widget.BaseAdapter 추상 클래스를 상속받은 어댑터들
- ArrayAdapter
- CursorAdapter
- SimpleAdapter
- RemoteViewsAdapter
- …
Adapter를 독자적으로 구현한 경우
- RemoteViewsService.RemoteViewsFactoryAdapter
- RecycleView.Adapter<T extends RecyclerView.ViewHolder>
대부분의 개발자들이 만나는 Adapter 클래스들은 BaseAdapter를 상속받아서 만들어졌다. 상속받아 구현된 Adapter들도 목적에 따라 필요한 함수들이 추가되었을 뿐 기본적인 구조는 android.widget.Adapter 인터페이스 같다. 예를 들면, 위젯을 위한 RemoteViewsAdapter라면 2개 이상같은 위젯이 런쳐에 올라와있는 경우를 한번의 수정이 모든 위젯에 동시에 반영되도록 함수가 추가된 정도의 차이만 있을 뿐이다.
대표적인 메소드
대부분 Adapter 인터페이스의 메소드들을 그대로 쓴다. 대표적인 메소드는 아래 두가지다.
- getItem()을 이용해 데이터를 반환한다.
- getView()를 이용해 데이터 셋 내의 아이템의 뷰를 반환한다.
위 그림에서 Client(안드로이드에서는 뷰)가 Adapter에 getItem()이나 getView()를 호출하면, Adapter가 Implementation(Adatee, 안드로이드에서는 데이터 셋)을 제어하여 뷰나 아이템을 반환하는 형식이 되겠다.
참고