Android/안드로이드 프로그래밍 Next Step

[Next Step] 5. 액티비티 생명주기

Diane_KIM 2023. 8. 27. 18:08

액티비티는 필요한 만큼만 유지

- 내부에 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();

 

 

액티비티에서 다른 액티비티를 시작할때 생명주기

  1. ActivityA는 onPause() 메서드를 실행 (백그라운드로 이동)
  2. ActivityB는 onCreate(), onStart(), onResume() 실행하고 포커스 갖는다. (포그라운드로 이동)
  3. ActivityA는 onStop()실행 (ActivityB가 전체화면을 덮어서 ActivityA는 보이지 않는다.)

여기서 유의해야할 점은 ActivityB가 onResume()을 호출한 다음에 ActivityA가 onStop()이 호출된다는 것! ActivityA에서 변경된걸  ActvityB에서 사용하려면 onPause에서 값을 저장해야함.

 

 

포그라운드 액티비티가 닫힐 때

  1. ActivityB는 onPause()실행 (백그라운드로 이동)
  2. ActivityA는 onRestart(), onStart(), onResume() 실행 (포그라운드로 이동)
  3. 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() 직접 호출은 권장하지 않음. 시스템 메서드는 함부로 엮지말고, 별도 메서드를 만들어 사용하는걸 권장