Android 4대 컴포넌트 (Activity의 launchMode)

SSY·2025년 2월 1일
0

AndroidFramework

목록 보기
3/3
post-thumbnail

시작하며

안드로이드에서 Activity의 실행 방식과 Task관리 방식 이해를 위해, 매니페스트 및 Intent에서 설정하는 launchMode와 개념을 포스팅하고자 한다.

launchMode란?

launchMode는 액티비티가 새로운 인스턴스로 생성될지, 기존 인스턴스를 재사용할지를 정의하는 속성으로 이는 ManifestIntent의 flag로 설정 가능하다.

Manifest의 launchMode

[standard]

Manifest든, Intent.flag든, 아무것도 설정하지 않았을 때 선택되는 기본 실행모드로, 액티비티 객체를 새로 생성한다. 아래 그림과 같이 BackStack or Task에 존재하는 Activity를 생성할 때, 무조건적으로 새로운 객체가 생성된다.

위 사진은 A Task 최 상단에 동일한 Activity가 있음에도 불구, 재활용 없이 새로운 객체를 생성한다. 즉, Back Stack에 어떤 Activity객체가 있든 새로운 것을 생성한다.

위 사진은 A TaskB Task가 나누어 존재할 뿐, 위와 같은 흐름이다. 즉, Task에 어떤 Activity객체가 있든 새로운 것을 생성한다.

위 사진은 A TaskB Task가 나뉘어 있다. 하지만 B TaskC_Activity가 존재함에도 불구, A TaskC_Activity 생성 시도 시, 그대로 생성한다. 즉, Task에 어떤 Activity객체가 있든 새로운 것을 생성한다.

[그 이후 launchMode의 공통점?]
이후 다룰 Manifest의 3가지 실행모드(singleTop, singleTask, singleInstance)는 standard와 달리 기존 Activity를 재사용한다는 공통점이 있다. 풀어 말하자면, 특정 Activity에서 BackStack or Task에 남아있는Activity를 또 다시 호출한다고 했을 때, 이는 기존 Activity의 인스턴스를 재호출함과 동시에 onNewIntent()생명주기 콜백 메서드를 호출한다는 의미이다.

[adb를 사용한 Activity백스택 조회 법]
adb shell dumpsys activity activities | grep "Hist.*com.sample.app"

[singleTop]

하나의 Back Stack의 최 상단엔 동일한 Activity는 1개임을 선언하는 실행모드이다.

아래 사진은 백스택 최 상단에 C_Activity가 존재한다. 이때 동일한 것을 호출했을 경우, 새로운 객체를 생성하는게 아니라 onNewIntent를 호출하며 기존 객체를 재사용하게 된다. 또한 사진 밑엔 adb명령어를 사용해 C_Actiity를 연속적으로 호출해서 결과를 확인해 보면, C_Activity는 최 상단에 1개만 존재하는 걸 볼 수 있다.

[Before]

[After]

하지만 아래 사진을 보면, 적재하려는 Activity가 연속적이지 않을 땐 재활용하는게 아닌, 새로운 C_Activity객체를 새로 생성하여 적재한다. 즉, singleTop이란 이름에 맞게, BackStack의 최 상단, Top엔 오로지 단 하나, single만 존재한다는 것이다.

[Before]

[After]

[singleTask]

전체 Task Stack에서 유일한 액티비티임을 선언하는 실행모드로 보통 2가지 시나리오를 인지하면 된다.

첫 번째는 자신을 시작시킨 ActivitytaskAffinity를 비교 후, 동일하다면 기존 Task에 적재한다. 반면, 그렇지 않은 경우 새로운 Task를 만들어 해당 Activity를 적재한다는 점이다.

두 번째는 실행시킨 singleTask가 선언된 Activity를 실행했을 때, 이 Activity가 이미 특정 Task에 존재하고, 그 위에 다른 Activity들이 존재할 경우, 이들을 모두 onDestroy()시켜버린 후, 호출한 singleTaskActivityonNewIntent()호출해가며 재활용 한다는 점이다.

아래 사진은 첫 번째 시나리오를 나타내고 있다. singleTask는 해당 Activity시작 시, 자신을 호출한 ActivitytaskAffinity와 자신의 taskAffinity의 동등성 비교를 진행한다. 만약 같다면 기존에 존재하는 Task에 적재하지만, 그렇지 않다면 새로운 Task를 생성해 적재한다.

[Before]

[After]

아래 사진은 새롭게 실행시키는 A_ActivitytaskAffinity가 다른 경우이다. taskAffinity가 다르므로 새로운 Task를 생성 후 이를 적재하는 모습이다.

[Before]

[After]

아래 사진은 두 번째 시나리오를 나타내고 있다. A Task의 밑에서 2번째에 A_ActivitysingleTask로 존재한다. 이때, 최 상단에서 이를 재호출 한다면, A_ActivityonNewIntent()호출로 기존 Activity를 재활용함과 동시에, 그 상위에 있는 Activity들을 모두 onDestroy()시킨다.

[Before]

[After]

하지만 아래 사진과 같이, 이미 존재하는 Task가 2개 이상인 경우도 있다. 만약 A TasksingleTask로 선언 한 A_Activity가 존재하며, 그 상단에 B_Activity/C_Activity가 존재한다. 이때, 포그라운드 상태인 B_Task에서 singleTask로 선언 한 A_Activity를 호출하면 어떻게 될까? singleTask는 앱 전체 Task상 오로지 1개의 Activity만 존재하도록 선언하는 시작모드인 만큼, A Task가 포그라운드로 올라오며, A_ActivityonNewIntent()를 호출함과 동시에 그 상위 Activity들을 onDestroy시킨다.

[Before]

[After]

[singleInstance]

singleInstance로 선언 한 Activity를 실행시킨다면 무조건 새로운 Task를 할당한다. 그 후, 이 Task에서는 그 어떠한 Activity는 적재될 수 없으며, 이전에 가용 가능한 Task에서 생성되도록 하는 시작모드이다.

[Before]

[After]

[singleInstancePerTask]
singleInstance와 기본동작은 동일하다. 다만, singleInstance에 존재하는 Activity는 전체 Task상 1개만 존재할 수 있지만 singleInstancePerTask는 여러 Task에서 해당 Activity를 포함 한 형태로 여럿이 존재할 수 있다는 점이 차이이다.

다만, singleInstancePerTask사용을 위해, Intent.flag를 아래와 같이 꼭 선언해줘야 한다.

Intent(this@A_Activity, A_Activity::class.java).apply {
  flags = FLAG_ACTIVITY_MULTIPLE_TASK or FLAG_ACTIVITY_NEW_DOCUMENT
  startActivity(this)
}

아래는 singleInstance를 선언 한 A_Activity의 재호출이다. 물론 Intent.flag로 위와 동일하게 준 상태이다. 그럼에도 불구, A_Activity객체 재생성이 아닌, onNewIntent()의 재호출 및 재활용하고 있음을 확인할 수 있다.

[Before]

[After]

반면, 아래는 singleInstancePerTask로 선언된 Activity를 여러번 반복 실행했을 때이다. 해당 Activity가 매번 새로운 Task와 함께 생성되는 것을 확인할 수 있다.

[Before]

[After]

Intent.flag의 launchMode

[FLAG_ACTIVITY_SINGLE_TOP]

이는 Manifest의 launchMode 중, 위에서 설명 한 singleTop과 동일한 동작이다. 설명은 이하 생략한다.

[FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP]

이는 Manifest의 launchMode 중, 위에서 설명 한 singleTask과 동일한 동작이다. FLAG_ACTIVITY_NEW_TASK는 새로 시작할 Activity에게 새로운 Task를 할당해주며, FLAG_ACTIVITY_CLEAR_TOP는 새로 시작하려는 Activity가 이미 특정 Task상에 존재하며 그 위에 다른 Activity들이 있을 때, 이들을 모두 onDestroy를 시켜준다. 그림을 포함한 설명은 생략한다.

참고

profile
불가능보다 가능함에 몰입할 수 있는 개발자가 되기 위해 노력합니다.

0개의 댓글