[Next Step] 5. 액티비티 생명주기
액티비티는 필요한 만큼만 유지
- 내부에 UI 액션이 많고, 로직이 많다면 우선 액티비티 고려
- 독립적인 화면이라면 액티비티가 더 적합
setContentView()를 쓰지 않는 경우도 있음
- 로직에 따라 분기해서 다른 액티비티를 띄우는 용도
- 예로 스키마에 따라 다른 Activity를 띄우기 위해 쓰기도 한다.
//호출하는 쪽
Uri uri = Uri.parse("doc://microsoft/0000");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
//받는 쪽
<activity android:name="XXXActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="doc"/>
<data android:scheme="xls"/>
<data android:scheme="ppt"/>
</intent-filter>
</activity>
* ACTION_VIEW : 다른 앱이나 시스템 앱을 호출하고, 해당 앱이 지정된 URI를 적절히 처리하여 데이터를 보여주도록 하는데 사용되는 액션
Lifecycle
딱 이것만 생각하자
- 액티비티가 보이기 시작하면 onResume()
- 액티비티가 가려지기 시작하면 onPause()
- 다른 액티비티가 전체를 가리면 onStop(), 종료되고 다시 돌아오면 onRestart(), onStart()
생명주기 메서드 호출 시점
(알아두면 개발하는데 많이 유용한)
- 시작할때 : onCreate -> onStart -> onResume
- 화면 회전할때 : onPause -> onStop -> onDestroy -> onCreate -> onStart -> onResume
- 다른 액티비티가 위에 뜰 때/전원 키로 화면 OFF할 때/홈 키 : onPause -> onStop
- 백 키로 액티비티 종료 : onPause -> onStop -> onDestroy
- 백 키로 기존 액티비티에 돌아올 때/홈 키로 나갔다가 돌아올때 : onRestart -> onStart -> onResume
* 액티비티는 onPause 이전까지가 포그라운드 라이프타임
* onCreate()에서 finish()를 호출하면 다른 생명주기 메서드를 거치지 않고 바로 onDestroy() 실행
* onActivityResult()는 onResume()보다 먼저 실행됨
액티비티 시작 메서드
startActivity(), startActivityForResult()
- startActivity : Context의 메서드로, Context가 전달된 곳이면 어디(Service, BroadcastReceiver, Application)든 호출 가능
- startActivityForResult() : Activity의 메서드. Activity끼리만 데이터 주고 받을 수 있음
* startActivity로 시작된 피호출자에서 getCallingActivity호출하면 null리턴. startActivityForResult()는 다름
* Activity의 getParent()는 자기 자신을 포함한(embed) 액티비티를 가리키는 것 (시작시킨 액티비티가 아니다)
startActivityForResult
- 2번째 파라미터에는 requestCode를 넣는데, 이때 0이상인 값을 넣어야함
- 동일한 태스크에 있을때만 유효
- resultCode는 RESULT_OK(-1)와 RESULT_CANCELED(0)를 주로 사용
- A -> B -> C 전달하는 방법
- A -> B : startActivityForResult
- B -> C : startActivity with FLAG_ACTIVITY_FORWARD_RESULT 플래그 사용
//ActivityA
startActivityForResult(new Intent(this, ActivityB.class), REQUEST_CODE);
//ActivityB
Intent intent = new Intent(this, ActivityC.class);
intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
startActivity(intent);
finish();
//ActivityC
Intent intent = new Intent();
intent.putExtra("value", "Android");
setResult(RESULT_OK, intent);
finish();
액티비티에서 다른 액티비티를 시작할때 생명주기
- ActivityA는 onPause() 메서드를 실행 (백그라운드로 이동)
- ActivityB는 onCreate(), onStart(), onResume() 실행하고 포커스 갖는다. (포그라운드로 이동)
- ActivityA는 onStop()실행 (ActivityB가 전체화면을 덮어서 ActivityA는 보이지 않는다.)
여기서 유의해야할 점은 ActivityB가 onResume()을 호출한 다음에 ActivityA가 onStop()이 호출된다는 것! ActivityA에서 변경된걸 ActvityB에서 사용하려면 onPause에서 값을 저장해야함.
포그라운드 액티비티가 닫힐 때
- ActivityB는 onPause()실행 (백그라운드로 이동)
- ActivityA는 onRestart(), onStart(), onResume() 실행 (포그라운드로 이동)
- ActivityB는 onStop(), onDestory() 실행 (종료)
생명주기 메서드 사용시 주의사항
- 리소스 생성/제거는 대칭으로 실행 (onCreate에서 리소스를 생성했다면 onDestroy에서 제거)
- suer.onXxx()호출 순서를 create, start, resume에서는 먼저, pause, stop, destroy는 나중에 실행
@Override
protected void onResume() {
super.onResume(); // onResume에서는 super 먼저
mLocationManager = new MyLocationManager();
}
@Override
protected void onPause() {
myLocationMager = null;
super.onPause(); // onPause에서는 super 나중에
}
- finish()는 호출하고 바로 리턴 필요. (리턴하지 않으면 리소스를 해제한 후에 다음 로직이 실행되면 NPE 발생 가능성이 있음.)
- onXxx() 직접 호출은 권장하지 않음. 시스템 메서드는 함부로 엮지말고, 별도 메서드를 만들어 사용하는걸 권장