안드로이드 액티비티. (Android Activity)

2016. 8. 4. 10:22


1. 안드로이드 앱 UI 표시.

일반적으로 안드로이드 시스템에서 앱이 실행되면, 전체 화면에 앱의 UI가 표시되고, 사용자가 입력한 화면 터치 또는 버튼 터치 등의 이벤트에 따라 앱의 기능이 수행됩니다. 이 때, 앱의 기능이 동작하는 과정에서, 최초 화면에 표시된 UI의 내용이 일부 바뀌거나 새로운 UI가 화면의 전체 영역에 표시되기도 하죠.


"구글 메일 앱"을 예로 들어 앱 동작 과정을 도식화 해 보도록 하겠습니다.

안드로이드 앱 UI 표시


자, 위에서 기술한 앱 실행 및 동작 과정에서 일어나는 UI관련 세 가지 주요 활동을 콕 찝어볼까요?

  1. 앱이 실행되면, 전체 화면에 앱의 UI를 표시.
  2. 사용자가 입력한 화면 터치 또는 버튼 터치 등의 이벤트 처리.
  3. 새로운 UI를 화면의 전체 영역에 표시.

여기서 굳이 "세가지 주요 활동(activity)"이라는 단어를 사용한 이유는, 바로 안드로이드 Activity가 앱에서 그러한 역할을 담당하는 주체이기 때문입니다.


위에서 "활동"이라는 사전적 의미의 단어 사용은 저의 주관적인 선택입니다. 안드로이드 공식 홈페이지에서는 Activity를 "작업"으로 명시하고 있습니다. Activity를 이해함에 있어 단어 선택에 따른 혼동이 없으시길 바랍니다.


1.1 안드로이드 Activity

안드로이드 Activity는 화면에 표시되는 UI 구성을 위해 가장 기본이 되는 요소입니다. 안드로이드 앱은 화면에 UI를 표시하기 위해 최소 하나의 Activity를 가져야 하며, 앱 실행 시 지정된 Activity를 실행하여 사용자에게 UI를 표시하게 됩니다.


여러 예제에서 작성한 "MainActivity"가 바로 앱 실행 시 최초로 보여지는 Activity이며, 안드로이드 스튜디오에서 자동으로 생성되는 템플릿 코드에서 MainActivity가 최초 실행되도록 지정되어 있습니다. (반드시 MainActivity라는 이름이어야 하는 것은 아닙니다. 프로젝트 생성할 때 입력하는 설정에 의한 결정일 뿐이므로 개발자가 원하는 이름으로 지정할 수 있습니다.)


앱 실행 시 시작되는 Activity 정보는 "AndroidManifest.xml" 파일에서 확인할 수 있습니다.

안드로이드 액티비티 정보


아래는 Activity 클래스의 계층 구조입니다. android.app.Activity에서 상속된, 다양한 용도의 Activity가 존재하는 것을 확인할 수 있습니다.

안드로이드 액티비티 클래스


그리고 android.content.Context에서 상속된 것을 확인하시기 바랍니다. 이는 Activity 클래스가 android.content.Context의 기능들을 사용할 수 있다는 것을 의미합니다. 또한 android.content.Context가 인자로 사용되는 곳에 Activity 클래스의 참조가 사용될 수 있다는 뜻이기도 하죠.


Activity와 Context의 관계에 대한 예제는 추후 다른 예제를 통해 살펴보도록 하겠습니다.

1.2 Activity의 UI 표시

안드로이드 Activity가 화면에 UI를 표시하는 역할을 수행한다고 해서, 자체적인 그리기 기능이 실행되어 화면을 그리는 것이 아닙니다. 대신, View 또는 ViewGroup의 다양한 조합을 화면에 배치함으로써, UI를 표시하는 것이죠.


Activity가 화면에 표시할 UI는 Layout 리소스 XML 파일(R.layout.XXX)이거나, android.view.View에서 상속받은 클래스(TextView, Button, ...) 이어야 하며, setContentView() 함수를 통해 화면에 출력될 Layout 리소스 XML ID 또는 View 클래스를 지정할 수 있습니다. 이런 관점에서 보면 Activity는 화면에 UI(View 또는 ViewGroup으로 구성된)를 표시하기 위한 틀이라는 개념이 되겠네요.


아래는 템플릿 코드에 의해 생성되는, "R.layout.activity_main"을 UI로 표시하는 코드입니다.

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        // 코드 계속 ...
    }

다음 코드는 TextView의 인스턴스를 하나 생성한 다음, Activity의 UI로 표시하는 예제입니다. (개념 이해를 위한 예제일 뿐, 일반적으로 거의 사용되지 않습니다.)

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        TextView textView = new TextView(this) ;
        textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 24) ;
        textView.setText("TEXT1") ;
        setContentView(textView) ;
    }

Empty 액티비티


1.3 Activity 실행.

현재 Activity에서 다른 Activity를 실행하는 방법은 startActivity()라는 함수를 호출하는 것입니다. 이름 그대로 "Activity를 시작(start)" 하는 함수죠. 그런데 Activity를 실행하는 방법과 관련하여 추가적으로 알아야 할 내용이 있습니다. 바로 Activity를 실행할 때, "어떠한 의도(Intent)를 가지고 Activity를 실행하는가"를 기술하는 과정이 필요하다는 것입니다.


의도(Intent)라고 하는 것은 아래와 같이 설명될 수 있겠네요. (다음에 나올 설명들이 다소 장황하게 느껴지더라도 양해 바랍니다.)



A라는 Activity를 실행하고자 한다.

만약 개발자가 앱 내에 A라는 Activity를 하나 만들고 이를 명시적으로(explicit) 실행하고자 한다면, "A라는 Activity를 실행"하려는 의도(Intent)를 가진다고 할 수 있습니다.

액티비티 명시적 실행


하지만 반드시 자신이 만든 Activity만을 실행 해야 하는(할수 있는) 것은 아닙니다. 다른 누군가가 이미 만들어 놓은 Activity를 실행하는 경우도 있죠. 예를 들어 아주 멋진 아이디어가 떠올라 "관리가 매우 편리한 전화번호부 앱"을 하나 만들었다고 가정해보죠. 표시된 전화번호 옆에 "전화걸기" 버튼을 배치한 다음, 버튼을 누르면 해당 전화번호로 전화를 거는 기능이 실행되도록 만드려고 합니다. 이 때, "전화번호부 앱" 내에 전화를 거는 기능을 위한 Activity를 새로 만들어야 할까요? 아니요. 그렇게 할 필요가 없습니다. 왜냐하면 안드로이드에서는 "전화걸기"를 위한 Activity가 이미 제공되고 있기 때문입니다. 앱 개발자가 할 일은 새로운 Activity를 만드는 것이 아니라, 시스템에 이미 설치된 "전화걸기" Activity가 실행되도록 만드는 것입니다.


위에서 A라는 Activity를 실행할 때는, A라는 이름을 정확하게 알고 명시적으로 실행할 수 있었습니다. 하지만 "전화걸기"를 위한 Activity는 직접 만든 것이 아니기 때문에 정확한 이름을 알지 못하죠. 따라서 명시적인 실행이 불가능합니다. 대신 다음처럼 목적을 기술하여 Activity를 실행할 수 있습니다.


"전화걸기"를 위한 Activity를 실행하고자 한다.

이런 경우, 대상이 명시적이지 않은 암묵적인(implicit) 의도(Intent)를 가지고 "전화걸기" Activity를 실행할 수 있습니다. "전화걸기를 수행(action)하는 Activity를 실행"하려는 의도로 말이죠.

액티비티 암시적 실행


1.3.1 Intent

위에서 Activity를 실행할 때 의도를 기술해야 한다고 했는데, 이를 위해 사용하는 것이 바로 Intent 클래스입니다. Intent는 사전적으로 "의도, 의향"이라는 의미를 가지고 있죠.

인텐트 의미


Intent가 사용되는 이유를 설명하기 위해 다소 글이 길어졌지만, Intent 클래스의 인스턴스를 생성하여 Activity를 실행하는 것은 매우 간단합니다.


위에서 예로 든, "A라는 Activity를 명시적으로 실행"하는 코드는 다음과 같습니다.

    Intent intent = new Intent(this, A.class) ;
    startActivity(intent) ;

암묵적인 실행 방법에 대한 코드는 다음과 같습니다.

    Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:010-999-9999"));
    startActivity(intent) ;

Intent에 대한 자세한 내용은 추후 다양한 예제를 통해 살펴보도록 하겠습니다.

1.4 Activity의 종료.

Activity가 실행된 후, 작업이 완료되어 해당 Activity를 종료하고자 한다면 finish() 함수를 호출하면 됩니다. 아니면 finishActivity() 함수를 호출하여 이전에 실행한 특정 Activity를 종료할 수도 있습니다.


하지만 구글에서는 이러한 함수의 직접적인 사용을 권장하지 않고 있습니다. 이는 안드로이드 시스템이 관리하는 Activity의 생명 주기에 영향을 줄 수 있기 때문입니다. 좀 더 자세한 내용은 관련 예제를 다룰 기회가 생기면 언급하도록 하겠습니다.

1.5 Activity 관리.

최초 Activity(예를 들면 MainActivity)가 실행되어 화면에 UI가 표시된 후에, 다른 Activity를 구성하여 사용할지 여부는, 전적으로 앱을 기획하는(또는 만드는) 기획자(또는 개발자)의 선택에 달려있습니다. 앱이 표시하고자 하는 내용과 사용 편의성 등을 고려하여 현재 Activity 내에서 내용을 갱신할지, 아니면 새로운 Activity를 실행할지 결정하면 되는 것이죠.


그런데 만약 새로 화면에 표시되는 UI 구성이 기존 Activity에 표시되는 내용과 완전히 구분되어 독립적으로 실행되고, "뒤로(Back) 가기" 버튼에 의해 기존 Activity 화면이 다시 표시되어야 하는 경우라면, 새로운 Activity로 만들 것을 권장합니다. 왜냐하면 안드로이드 시스템은 새로운 Activity를 실행하면서 기존에 실행 중이던 Activity를 "Back-Stack"이라는 곳에 자동으로 저장하고, "뒤로(Back) 가기" 버튼을 누르면 이전에 저장된 Activity를 Back-Stack에서 꺼내어 실행해주기 때문입니다. 물론 "뒤로(Back) 가기" 버튼이 눌려질 때 실행되고 있던 Activity는 화면에서 사라지고, 실행이 종료됩니다.

액티비티와 백스택


"Back-Stack"에서 "Stack"이라는 용어가 의미하는 자료구조를 떠올리면 알 수 있듯이, "Back-Stack"에 쌓이는 Activity는 LIFO(Last-In-First-Out) 구조로 관리됩니다.

2. 참고

.END.


ANDROID 프로그래밍/ACTIVITY