Configuration : 컴포넌트에서 어떤 리소스를 사용할지 결정하는 조건, 이 조건은 FW에서 정해져 있음
android.content.res.Configuration 멤버변수
- densityDpi, fontScale, keyboard, locale, orientation, screenLayout... 17개
- fontScale, local은 단말의 환경 설정에서 정할 수 있는 사용자 옵션, 나머지는 단말 현재 상태
리소스 반영
- 언어나 화면회전 같은 리소스 변경은 액티비티 재시작해서 새로운 리소스로 적용되는 방식을 사용 (액티비티 외의 다른 컴포넌트는 구성이 변경되어도 재시작X)
- 구성변경에 의해 액티비티 재시작되면, 하나의 인스턴스를 가지고 새로 초기화해서 재사용하는 것이 아니다. 기존 인스턴스는 onDestory까지 실행하고, 새로운 인스턴스가 onCreate 부터 실행
메모리 누수 가능성 있는 경우
- Activity 목록 참조 : Activity인스턴스를 컬렉션에 모아두고, 액티비티가 종료할 때 제거해야하는데 실수로 빠뜨렸을 때
- Activity의 내부 클래스나 인명 클래스 인스턴스가 Activity 에 참조를 갖고 있고, 인스턴스를 외부에 리스너로 등록한 경우에 해제하지 않으면 발생. (내부 클래스에서 XXActivity.this 를 쓸 수 있으면 Activity 에 대한 참조를 가지고 있는것) => 권장 방법 : 단순 내부 클래스는 정적 내부 클래스로 생성
- 싱글톤에서 Context가 아닌 Activity 전달시 참조가 남아 문제 발생
- AsyncTask에서 Activity 참조 : AsyncTask가 오래 걸리면 OOM 발생 가능성 있음
* 구성변경시 프레임워크 동작 : system_server에서 동작하는 ActivityManagerService에서 앱 프로세스의 메인 클래스인 ActivityThread에 새로운 Configuration을 전달한다
* Configuration은 한순간에 1개의 값만 존재한다
태스크 : 액티비티 작업 묶음 단위
예를들어, 사진 리스트를 보고, 상세를 살펴보고, 사진을 올리려고 카메라를 실행시키는 행위를 할때 보여지는 3개의 액티비티가 하나의 태스크가 되는데, 2개의 앱이 하나의 태스크가 된다.
* taskAffinity : Activity 실행 시 신규 task 를 만들 경우 어느 task 에 속할지 지정하는 것. (디폴트로 앱의 패키지명이 설정됨)
태스크 속성을 부여하는 2가지 방법
1. 호출자에서 '너를'이렇게 다루겠어'
2. 피호출자에서 '나를 이런식으로 취급해줘'
1번째 호출자가 피호출자에게 속성을 부여하려면 Intent 플래그에 지정
- Intent에 setFlag(int flags) 파라미터에 or 연산(|)으로 여러개를 전달 가능
- Intent 플래그에 전달하는 값은 피호출자의 launchMode보다 우선해서 적용된다.
- 많이 쓰는 플래그들
- FLAG_ACTIVITY_SINGLE_TOP : singleTop launchMode와 동일한 효과
- FLAG_ACTIVITY_NEW_TASK : singleTask launchMode와 동일한 효과
- FLAG_ACTIVITY_CLEAR_TOP : 스택에서 피호출자보다 위에 있는 액티비티를 종료시킨다. (스택 A, B, C 에서 C에서 이 플래그 이용해 B를 시작하면 A, B만 스택에 남는다)
- FLAG_ACTIVITY_CLEAR_TASK : 피호출자가 시작되기 전에 관련된 스택이 모두 제거된다. 이 플래그는 FLAG_ACTIVITY_NEW_TASK와 함께 사용되어야 한다. (로그아웃하고, 다른 아이디로 로그인할때 태스크를 정리하고 메인 엑티비티를 새로 시작할때 사용)
- FLAG_ACTIVITY_REORDER_TO_FRONT : 스택에 동일한 액티비티가 이미 있으면 그 액티비티를 스택의 맨 위로 올린다. (FLAG_ACTIVITY_CLEAR_TOP 플래그와 함께 사용하면 옵션이 무시됨, 호출자가 액티비티일 때만 정상적으로 재배치 동작)
2번째 피호출자에서 속성을 부여하는 방법은 액티비티 선언에 android:launchMode로 지정
- launchMode 는 standard, singleTop, singleTask, singleInstance
- singleTask와 singleInstance는 1개의 인스턴스만 존재
- standard : 기본값, 매번 새로운 액티비티 인스턴스를 생성해서 Intent 전달
- singleTop : 호출하고자 하는 액티비티가 이미 topActivity에 있다면 새로 생성하지 않고 onNewIntent()로 Intent 전달. (top에 없으면 standard와 동일하게 동작)
- singleTask : 태스크에 이미 동일한 액티비티의 인스턴스가 있으면, 새로 생성하지 않고 onNewIntent()로 전달. top에 없으면 새로운 태스크를 만들고 액티비티는 새로운 태스크의 baseActivity가 된다.
- 예로 B가 singleTask고, A->B->C 호출에서 B를 호출할때 C는 스택에서 제거가 되고 A->B 의 onNewIntent() 호출됨
- singleInstance : 태스크에 들어가는 액티비티가 하나밖에 없는 것.
- 예로 A3가 singleInstance고, A1->A2->A3->A4 호출하면 A3는 별도의 태스크가 되므로 [A1,A2,A2], [A3] 2개의 태스크로 된다.

<activity-alias> 선언
제거된 액티비티 대체
- SplashActivity를 더이상 사용하지 않고 MainActivity로 보여주기로 했는데, 기존에 설치한 숏컷이나 링크가 남아있는 경우
<activity-alias
android:name=".SplashActivity"
android:targetActivity=".MainActivity"/>
FLAG_ACTIVITY_CLEAR_TOP 한계 해결
스택에 [A,B,A,B] 액티비티가 있을때 B에서 FLAG_ACTIVITY_CLEAR_TOP 플래그를 전달해서 A를 시작하면, [A,B,A] 로 남는다.
이때 [A] 만 남게 할 수 있는 방법은 A에 별명을 지어주고 첫번째 액티비티 A가 시작할때는 별명(FirstA)으로 시작하는것.
그럼 스택에는 [FirstA,B,A,B] 가 있고, 다음과 같이 Component 클래스에 별명을 전달해서 액티비티를 시작
Intent intent = new Intent().setComponent(
new Component(this, "com.suribada.someapp.FirstActivityA"));
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
'Android > 안드로이드 프로그래밍 Next Step' 카테고리의 다른 글
[Next Step] 5. 액티비티 생명주기 (0) | 2023.08.27 |
---|---|
[Next Step] 4. Context 클래스 (0) | 2023.08.25 |
[Next Step] 3. AsyncTask (0) | 2023.08.13 |
[Next Step] 3. 스레드 풀 사용 (0) | 2023.08.12 |
[Next Step] 3. HandlerThread 클래스 (0) | 2023.08.09 |