: 태스크는 액티비티 작업 묶음 단위이다. 여러 개 앱의 액티비티가 하나의 태스크가 될 수 있고 하나의 앱에서의 액티비티들이 다수의 태스크로 이루어질 수 있다. 태스크는 흔히 액티비티 스택, 백스택이라고 불리기도 한다. 태스크의 저장 방식이 스택 방식(LIFO)이기 때문이다. 태스크에서 액티비티가 쌓이는 방식은 중요하다. 예로 알람 앱을 실행 후 메인 화면(A)에서 알람 설정(B) 액티비티로 이동했고 홈 버튼을 눌러 태스크를 백그라운드로 보냈다. 그리고 내가 예전에 맞춰 놓은 알람 시간이 되 알람 대화상자(C) 액티비티가 떴다. 그렇다면 알람 대화상자(C) 액티비티가 백그라운드에 있는 태스크에 속하게 되 기존의 알람 태스크를 포그라운드로 불러오고 백 버튼을 누르면 C에서 B 액티비티로 가도록 해야 할까? 아니면 알람 대화상자(C) 액티비티를 새로운 태스크로 생성해 백 버튼을 눌러도 백그라운드에 기존의 알람 앱 태스크가 있도록 해야 할까? 이런 경우 때문에 규칙을 정해야 한다. 규칙을 정하기 위해서는 태스크 관리가 중요하다.
- 태스크 상태
: 태스크는 홈 키를 통해서 언제든지 포그라운드에서 백그라운드로 갈 수 있다. 또한 백그라운드에서 포그라운드로도 갈 수 있다. 이 때 이용하는 메서드가 moveTaskToBack(boolean) 이다. 인자에 false가 들어가면 태스크 루트일 때만 백그라운드로 이동이 가능하고 true이면 언제든지 이동 가능하다. 이 메서드는 카카오톡의 '암호 잠금 해제' 액티비티를 구현할 때 무조건 사용된다. 카카오톡을 백그라운드에서 포그라운드로 불러올 때나 처음 시작할 때 암호 설정을 해놓았다면 '암호 잠금 해제' 액티비티가 무조건 나타난다. '암호 잠금 해제' 액티비티는 기존 카카오톡 액티비티 백스택의 맨 위로 올라가기 때문에 암호를 맞게 입력했다면 '암호 잠금 해제' 액티비티를 종료하면 된다. 하지만 사용자가 Back 버튼을 누를 시에는 해당 액티비티를 그냥 종료시키면 안 된다. 백스택의 가장 위에 있기 때문에 액티비티를 종료하면 기존 카카오톡 액티비티가 나오기 때문에 암호 액티비티로써 역할을 못하게 된다. 그래서 사용자가 Back 버튼을 누를 시 원래 카카오톡 액티비티를 보이지 않게 하기 위해서 태스크를 백그라운드로 이동하는 방법을 사용한다. 이 때 '암호 잠금 해제' 액티비티의 onBackPressed() 메서드를 오버라이드해 moveTaskToBack(true)를 호출하면 된다.
- taskAffinity 속성
: taskAffinity 속성은 AndroidManifest.xml에 기술하는 액티비티 속성값이고 액티비티가 관련된 태스크에 들어갈 때 참고하는 값이다. 값을 명시하지 않을 시 디폴트로 앱의 패키지명이 된다. taskAffinity 속성은 각 액티비티에도 있지만 태스크에도 해당 속성을 가진다. 태스크의 taskAffinity 속성값은 태스크를 시작한 액티비티의 taskAffinity 값이 된다. 태스크의 taskAffinity가 언제 이용되는 지 예로 살펴보자. 만약 액티비티가 android:launchMode=singleTask로 설정되거나 Intent에 FLAG_ACTIVITY_NEW_TASK가 설정되 있다면 액티비티는 태스크의 taskAffinity가 액티비티의 taskAffinity와 동일한 것을 찾아 그 태스크에 액티비티가 속하게 된다. 참고로 FLAG_ACTIVITY_NEW_TASK는 무조건 새로운 태스크를 생성하지 않는다. taskAffinity 값에 따라 달라진다. 액티비티 자신과 같은 taskAffinity 값을 가진 태스크가 있다면 그 태스크에 액티비티가 포함되고 같은 게 없다면 자신의 taskAffinity 값으로 태스크를 새로 만든다.
추가로 startActivity를 할 시 특별한 옵션이 없다면 피호출자 액비비티는 호출자 액티비티의 백스택에 쌓인다. 따라서 액티비티가 아닌 서비스나 브로드캐스트 리시버에서 startActivity를 그냥 호출하면 오류가 발생한다. FLAG_ACTIVITY_NEW_TASK 옵션을 붙여 특정 태스크에 들어가도록 해줘야 한다.
- android:launchMode 태스크 속성
1. standard : 디폴트 값이다. 백스택의 가장 위에 액티비티를 추가한다.
2. singleTop : 호출할 액티비티가 백스택 가장 위에 있을 시 새로 생성하지 않고 onNewIntent() 메서드로 Intent를 전달한다. 가장 위에 없다면 standard 방식이 된다.
3. singleTask : 태스크에 해당 액티비티가 하나 밖에 없어야 한다. 액티비티의 taskAffinity와 동일한 태스크가 존재하고 해당 액티비티가 태스크에 있을 시 onNewIntent()를 호출한다. 해당 액티비티가 없다면 태스크의 가장 위에 추가된다. 태스크도 없다면 새로 태스크를 생성한다. 예로 B 액티비티를 singleTask라고 설정했다고 하자. A->B->C로 호출했을 때 모두 같은 taskAffinity 값을 가진다면 태스크에 [A,B,C]가 된다. A->B->C->B 순서로 호출했을 때는 C가 제거 되고 onNewIntent가 호출되고 태스크는 [A,B] 가 된다. 만일 B의 taskAffinity만 다를 때는 A->B->C 순서로 호출했다면 [A], [B,C] 가 된다. 특히하게 C는 A와 같은 태스크에 있지 않는다. C가 singleTask이거나 FLAG_ACTIVITY_NEW_TASK 플래그가 있어야 [A,C], [B]가 된다. 여기서 A->B로 이동했을 때 즉 다른 태스크로 전환했을 때는 약간의 딜레이가 발생한다. B 액티비티가 보이기 전에 검은 화면이 잠시 보이게 된다. 따라서 태스크를 바꾸게 되면 이런 딜레이에 고려해야 한다.
4. singleInstance : 태스크에 들어가는 액티비티는 1개 밖에 없고 액티비티 또한 백스택 안에 하나여야 한다. 예로 B 액티비티가 singleInstance이고 A,B,C의 taskAffinity 값이 같다고 하자. A->B->C 순서로 호출했을 시 [B], [A,C]가 된다. C 액티비티에서 Back 버튼을 누를 시 A 액티비티가 보인다. 만약 C가 Dialog Activity여서 배경에 다른 액티비티가 보인다고 하면 배경으로 B가 아닌 A 액티비티가 보인다. 참고로 최근 앱 목록에서는 [B], [A,C]가 별도로 보이지 않는다. 최근 앱 목록은 taskAffinity 값을 분류 기준으로 삼기 때문이다. B의 taskAffinity 값을 다른 값으로 바꾸면 최근 앱 목록에 [B]와 [A,C]가 보인다.
- Intent 플래그
<activity-alias android:name=".FirstActivityA" android:targetActivity=".ActivityA"/> Intent intent = new Intent().setComponent( new Component(this,"com.example.app.FirstActivityA")); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); startActivity(intent);
5. FLAG_ACTIVITY_REORDER_TO_FRONT : 스택에 동일한 액티비티가 있다면 그 액티비티를 스택의 맨 위로 올린다. 단 FLAG_ACTIVITY_CLEAR_TOP과 같이 사용 못 한다.
'안드로이드 > 기본' 카테고리의 다른 글
안드로이드 커스텀 뷰 만들기 (2) | 2017.08.03 |
---|---|
마커(Marker) 인터페이스, 어노테이션(Annotation) 활용 (0) | 2017.08.03 |
안드로이드 슬립 상태 대처하기 (0) | 2017.08.02 |
안드로이드 액티비티(Activity) 생명주기 총정리 (0) | 2017.08.02 |
minSdkVersion, targetSdkVersion, compileSdkVersion 란? (0) | 2017.07.30 |