안드로이드의 액티비티(Activity)
저번 글에서 안드로이드의 4가지 컴포넌트에 대해 간단하게 소개했다. 이번 글에서는 4가지 컴포넌트 중에서 가장 많이 사용하는 액티비티(Activity) 컴포넌트와, 생명주기에 대해 알아보자.
액티비티
안드로이드에서 액티비티 컴포넌트는 이름과 같이 사용자가 어떠한 활동 할 때 실행되는 컴포넌트이다. UI를 제공하여 사용자와 상호작용을 하며, class에서 activity를 상속받아 사용할 수 있다. 보통 앱은 여러 화면으로 구성되어 있어 여러 액티비티로 구성되어있다고 할 수 있다. 예를 들어 앱을 시작할 때 나오는 로그인 화면, 로그인을 했을 때 이동하는 메인화면 등 모두 각각의 액티비티들이다. 액티비티를 생성하면 .kotlin(또는 .java) 클래스 파일과 .xml파일이 함께 생성된다. .xml파일은 UI를 만드는 파일이며, 클래스 파일은 .xml파일에 만들어놓은 버튼 등 UI에 기능을 붙여 여러 동작이 가능하도록 만들 수 있다.
xml연결 및 manifest에 액티비티 추가
액티비티를 생성하는 방법은 총 2가지가 있다. 안드로이드 스튜디오에서 new-activity로 추가하는 방법과, 직접 클래스 파일과 xml파일을 만들어 사용할 수 있다. 첫 번째 방법으로 액티비티를 추가하면 클래스 파일과 xml연결, manifest추가 모두 알아서 생성해 준다. 하지만 직접 클래스 파일과 xml파일을 생성했다면, 이 파일들을 연결해주고 manifest에 액티비티를 추가해줘야 한다. 첫 번째 방법으로 액티비티를 생성하는 경우 이 과정이 필요 없지만, 코드를 구성하다 보면 파일이 서로 꼬이기도 하고, 어쩔 땐 툴에서 액티비티로 생성했음에도 manifest파일에 추가가 안돼서 한참 헤맸던 적이 있다. 과정을 알아두면 문제가 생겼을 때 빠르게 대처도 가능하니 한번 읽어보는 것을 추천한다:)
클래스 파일과 xml파일을 생성했다면, 클래스 파일과 xml파일을 연결해줘야 한다. MainActivity.kt파일과 activity_main.xml파일을 위 그림과 아래 코드들은 MainActivity.kt파일과 activity_main.xml파일을 만들었다고 가정한다. MainActivity.kt와 activity_main.xml파일을 연결하려면 MainActivity.kt의 onCreate메서드 안에 setContentView(R.layout.activity_main) 코드를 넣어주면 된다.
//클래스 파일에 activity_main.xml 연결
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
클래스 파일과 xml파일을 연결했다면, 액티비티를 사용할 수 있도록 manifest.xml파일에 액티비티 정보를 추가해줘야 한다. 아래 예시에는 MainActivity하나만 등록되어 있지만, 앱을 만들면서 액티비티를 추가하면 manifest.xml에도 액티비티가 추가된다. InteliJ나 안드로이드 스튜디오에서 activity를 추가하면 manifest파일에 자동으로 등록된다. 하지만 클래스에 직접 activity를 상속받고 xml을 연결했다면 직접 manifest파일에 등록해줘야 한다.
<manifest ... >
<application ... >
<activity android:name="com.example.myapp.MainActivity" ... >
</activity>
</application>
</manifest>
그리고 인텐트 필터(intent filter)를 설정해준다. 먼저 인텐트란, 메시지 객체로 액티비티끼리 통신을 하기 위해 사용한다. 우리가 특정 화면에서 다음 화면으로 넘어갈 때 인텐트를 사용하며, 인텐트로 다음 화면에 필요한 정보들을 포함하여 함께 보낼 수도 있다.
인텐트 필터는 어떤 인텐트를 받을지 '필터'의 역할을 한다. 인텐트 필터에는 action, category, data 속성으로 구성되어 있는데 이 속성들로 어떤 데이터를 전송하고, 어떤 데이트를 보낼지 등을 선택할 수 있다. 우리가 앱을 만들기 위해 프로젝트를 생성하면 MainActivity가 생성되는데, 이 MainActivity에 인텐트 필터가 적용되어 있고, <action> 속성에 ACTION_MAIN이 적용되어 있다. ACTION_MAIN은 앱을 시작할 때 시작할 액티비티를 지정하는 액션이다. (인텐트와 인텐트 필터에 대한 내용은 다른 포스트에서 더 자세하게 다루도록 하겠다.)
<activity android:name=".ExampleActivity" android:icon="@drawable/app_icon">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
액티비티 생명 주기(Activity Lifecycle)
액티비티를 생성해서 액티비티에는 생명 주기가 있다. 생명 주기란 이름 그대로 액티비티가 생성되는 순간부터 액티비티가 죽는 순간까지 단계를 나누어 놓았다. 왜 액티비티에 생명 주기를 만들었을까? 우리가 앱을 사용할 때를 한번 생각해 보자. 카카오톡으로 친구들과 카톡을 하다가 유튜브 앱을 켜고 동영상을 보다가 네이버 앱을 켜서 뉴스 좀 보다가 다시 친구들과 카톡을 한다. 이때 앱이 종료되고 다시 켜지는 것이 아니라 다른 앱을 켜기 전의 화면으로 다시 돌아간다. 또한 뒤로 가기 버튼을 눌러도 이전 화면이 유지된 채로 보인다. 우리는 화면에서 안 보이는 순간 앱이 종료될 것이라고 생각하지만 그렇지 않다. 이처럼 액티비티는 단순하게 화면에서 사라진다고 해서 종료되는 것이 아니며, 사용자가 어떤 액션을 취했는지(뒤로 가기, 홈버튼, 다른 앱으로 전환 등)에 따라 앱을 재실행했을 때 보이는 화면과 데이터가 달라야 한다. 또한 앱이 비정상적으로 강제 종료될 때도 데이터를 백업할 시간이 필요한데, 이럴 때 액티비티 생명주기를 활용해서 처리할 수 있다.
액티비티 생명 주기는 위 그림과 같다. 생명 주기를 외우기가 힘든데, 표시한 색과 같이 위아래 세트로 기억하면 외우기 좋다.
- OnCreate, OnDestroy
OnCreate는 액티비티가 실행될 때 딱 한 번만 실행된다. 처음 액티비티가 실행되면 view를 생성하고, onCreate에서 처리해야 할 일이 완료되면 OnStart, OnResume을 순서대로 실행한다.
OnDestroy는 View를 폐기하고, 액티비티를 실행하면서 사용한 리소스를 해제한다. 메모리에서 완전히 view를 폐기하는 단계로, OnDestory가 호출되면 앱이 완전히 종료되었다고 할 수 있다. - OnStart, OnStop, OnRestart
OnStart는 화면에 표시되기 직전 단계로 주로 통신하거나 센서 처리가 필요할 때 사용한다. 그리고 UI를 관리하는 코드를 초기화한다.
OnStop은 다른 액티비티가 현재 화면 전체를 가리거나, 액티비티가 중지될 때 호출된다. OnStop에서는 메모리가 부족한 경우, 강제 종료되어 OnCreate를 다시 호출하는 경우와 사용자가 다른 액티비티를 호출하여, 다시 돌아오는 경우 OnRestart를 호출하고 OnStart과정부터 시작하는 경우로 나뉜다.
OnRestart는 조금 특이한 형태로, OnStop에서 사용자가 다른 액티비티를 호출하고 다시 돌아오는 경우 OnRestart가 호출된다. 그리고 OnStart-OnResume을 거쳐 사용자에게 화면을 다시 보여준다. - OnResume, OnPause
OnResume은 사용자에게 화면이 보이는 단계이다. OnResume에서 사용자와 상호작용을 한다. 그리고 사용자가 다른 앱을 실행하거나 앱 종료, 화면이 꺼지기 등 방해 요소가 있기 전까지는 OnResume상태에 머무른다.
OnPause단계는 OnResume단계에서 방해 요소가 발생하면 OnPause단계로 넘어간다. OnPause단계에서 사용자가 다시 화면으로 돌아가면 OnResume을 호출하여 화면을 보여준다.
OnPause와 OnStop의 차이가 조금 모호한 거 같다. 필자가 공식 문서와 책을 봤을 때, OnPause는 사용자가 아주 잠깐 다른 활동을 하고 돌아오거나, 화면이 일부분만 가려진 경우(팝업창 등) 호출되어 사용자가 다시 돌아오면 OnStart부터 시작하는 게 아니라 다시 OnResume단계부터 시작할 수 있도록 조치한다. 반면에 OnStop은 OnPause보다는 좀 더 깊은(?) 단계로 완전히 다른 앱을 실행하거나 홈버튼을 눌러 화면에서 완전히 사라지면 호출되는 것 같다.(혹시 설명이 잘못되었거나 명확한 구분 방법을 아시는 분은 댓글로 알려주시면 감사하겠습니다!! 공부하다 알게 되면 다시 글을 수정하겠습니다!)
마무리
이번 글에서는 안드로이드 컴포넌트 중에서 가장 많이 사용하는 액티비티를 사용하는 방법과 생명주기에 대해 알아봤습니다. 안드로이드는 웹과 다르게 많은 상태를 가지고 있어 액티비티 생명주기도 복잡하고 이해하기 조금 난해한 부분도 많은 것 같습니다. 아직은 내용이 크게 와닿지는 않지만 더 공부하다 보면 지금은 맞지 않는 퍼즐이 끼워 맞춰지는 날이 올 것이라고 생각합니다! 다음 글에서는 인텐트와 액티비티 상태에 대한 글을 작성할 예정입니다. 읽어주셔서 감사합니다.
Reference
https://developer.android.com/guide/components/activities/intro-activities
https://developer.android.com/guide/components/activities/activity-lifecycle
작성한 글에 잘못된 부분이나 문제가 있는 경우 댓글에 작성해 주시면 수정하도록 하겠습니다. 질문도 환영합니다! :)