View, Activity, 그리고 Fragment

안드로이드에서는 기본적인 UI 요소를 View라고 부르며, 모든 UI 요소들은 View 클래스(android.view.View)의 서브 클래스들이다. View는 크게 Widget과 Layout으로 구분할 수 있다. Button, TextView, CheckBox와 같은 시각적인 UI 요소들을 Widget(또는 Component)이라고 하고, 화면에서 보이지는 않지만 다른 View들을 담는 container 역할을 하는 것을 Layout이라고 한다. 따라서, View는 계층 구조로 생성하여 사용할 수 있으며, 이 때 계층상의 상위 View를 부모 뷰, 하위 View를 자식 뷰라고 한다. 하나의 View는 화면 상에서 하나의 직사각형 영역을 나타낸다. 따라서, View는 해당 직사각형 영역에 UI를 그리는 것과, 이곳에서 발생하는 이벤트를 처리하는 역할을 수행한다. 각 View에서 발생하는 이벤트를 처리하기 위해서는 각 View 마다 다른 View들과는 중복되지 않는 id가 정의되어 있어야 하며, 이 외에도 width, height, background, margin 등의 속성들을 해당 XML 파일(아래에서 설명하는 해당 Activity의 XML 파일)에 정의하여 사용할 수 있다.

태블릿을 제외한 대부분의 안드로이드 디바이스들은 화면의 크기가 작기 때문에 여러 개의 화면으로 하나의 애플리케이션을 구성하고, 일정 시점에서는 한 개의 화면만을 보여주는 경우가 많다. 이 때, 하나의 화면과 밀접하게 연관되어 있는 독립형 실행 모듈을 Activity라고 한다. Activity는 재사용성의 초점을 맞추어서 설계된 개념이다. 하나의 Activity는 레이아웃을 설정하는 하나의 XML 파일과 실제 작업을 수행하는 하나의 JAVA 파일로 구성되어 있는데, 다른 Activity와는 독립적으로 구성되기 때문에, 필요시 그대로 복사해서 다른 앱 패키지에서도 사용할 수가 있다. Activity는 앱이 실행되는 과정에서 일련의 생명주기(life-cycle)를 겪는다. Activity는 각 생명주기 상태가 변경될 때마다 자동적으로 호출되는 콜백(callback) 함수들(onCreate, onRestart, onStart, onResume, onPause, onStop, onDestroy)을 가지고 있다. Entire lifetime은 onCreate~onDestroy, visible lifetime은 onStart~onStop, foreground lifetime은 onResume~onPause 호출 사이의 실행시기를 의미한다.

Fragment는 태블릿이 등장하면서 생겨난 필요성에 의해 안드로이드 3.0 허니컴(HoneyComb)에서 새롭게 추가된 요소이다. 앞에서 설명한 바와 같이 대부분의 안드로이드 디바이스들은 화면의 크기가 작기 때문에 한 시점에서는 하나의 Activity와 연동된 하나의 화면을 보여주는 것으로 충분했다. 이메일 앱의 예를 들면, 일단 실행후 이메일 제목 리스트를 보여주는 화면이 보이고, 특정 제목을 클릭하면 해당 이메일의 내용을 보여주는 화면을 보여주는 식이다. 하지만, 태블릿이 등장하면서 화면의 크기가 커지게 되었고, 굳이 한 시점에서 하나의 화면만을 보여줄 필요가 없어졌다. 오히려 한 시점에서 하나의 화면만을 보여주게 되었을 때 많은 공백이 생겨서 구성이 깔끔하지 못한 문제가 발생하게 되었다. 큰 화면을 깔끔하고 효율적으로 활용하기 위해서는 하나의 화면을 분할하고 동시에 여러 개의 화면을 보여줄 수 있어야 하는데, 두 개 이상의 Activity를 하나의 화면에 구성하는 것이 불가능하기 때문에 나오게 된 것이 바로 Fragment이다. 물론 하나의 Activity 상에서도 여러 개의 View를 이용하여 이러한 기능을 수행할 수 있지만 재사용성이라던지 생애주기 관리 측면에서 많은 문제점을 가지고 있기 때문에 Fragment를 사용하는 것을 권장한다. 하나의 Activity는 여러 개의 Fragment를 가질 수 있고, 하나의 Fragment는 여러 개의 View를 가질 수 있다. 하나의 Activity 내에서 특정 Fragment를 다른 Fragment로 교체하는 것도 가능하다. 이렇듯 Fragment를 이용하면 쉽게 넓은 크기의 화면을 다양하게 분할하여 효율적으로 사용할 수 있다. 특히, 하나의 Activity 내에서 UI의 구성이 복잡할 때 각 요소를 Fragment로 모듈화하여 사용하게 되면 효율적인 관리가 가능하게 된다. Fragment 또한 생명주기를 가지고 있으며 Activity의 생명주기와 거의 유사하다. Activity에는 없는 onAttach()와 onDetach()라는 생명주기 콜백 함수를 가지고 있는데, onAttach()는 Fragment가 Activity에 연동될 때 호출된다.

activity_view_fragment

왼쪽 그림은 Activity-View 구조의 예이고, 오른쪽 그림은 Activity-Fragment-View 구조의 예이다. Fragment는 Activity와 View 사이에 존재하는 레이어의 개념으로 생각하면 이해하기 쉽다. Activity-Fragment-View 구조를 사용하면 오른쪽 그림의 예에서 초록색 Fragment를 제거하고 동적으로 다른 Fragment를 새롭게 추가하는 등의 작업을 자유롭게 수행할 수 있다.

Activity에 Fragment를 붙이는 방법에는 static 방식과 dynamic 방식이 있다.

Design 모드에서 <fragment>를 drag & drop하여 간단하게 붙일 수 있는데, 이것이 static 방식이다. 이렇게 하면 Activity의 XML 파일에 다음과 같은 구문이 추가된다. (물론 Text 모드에서 XML 파일에 직접 타이핑을 해주어도 동일한 결과를 얻을 수 있다.)

<fragment
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:name="com.example.administrator.fragmentexample.MyFragment"
    android:id="@+id/fragment1"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    tools:layout="@layout/my_fragment" />

Activity가 실행중일 때 런타임(run-time) 방식으로 fragment를 붙이는 것도 가능한데 (물론 제거하는 것도 가능함), 이것을 dynamic 방식이라고 한다. Dynamic 방식에서는 FragmentManager를 사용하여 다음과 같이 바인딩을 한다.

MyFragment fragment = new MyFragment();

//Bundle bundle = new Bundle();
//fragment.setArguments( bundle );

FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add( R.id.layout, fragment ); // add 대신 replace도 가능
fragmentTransaction.commit();

FragmentActivity는 Fragment가 포함되기 이전인 안드로이드 3.0 허니컴(HoneyComb) 환경에서 Support Package를 이용하여 Fragment를 다루기 위해 사용하는 클래스이다. 따라서, 최신 안드로이드 버전에서는 Fragment를 다루기 위해 FragmentActivity 대신 Activity를 사용하는 것을 권장한다. 참고로 Activity에서 Fragment를 사용하기 위해서는 android.app.Fragment를 import하고, FragmentActivity에서 Fragment를 사용하기 위해서는 android.support.v4.app.Fragment를 import하여 사용한다.

답글 남기기