본문 바로가기

Development/Android Studio

(Android Studio) Chapter16. Life Cycle

1. 개념

    - 모바일이 앱이 실행되고 종료될 때까지 거치는 주요 단계

    - 안드로이드 앱을 실행하고, 다른 엑티비티가 덮어 씌여지거나, 홈 화면으로 나가거나, 다시 돌아오거나, 빠져나갔을 때 실행 할 기능들을 선언

    - AppCompatActivity 클래스에서 기본으로 제공하는 메소드들로 구성

    - 생명주기 묘사도

출처: https://developer.android.com/guide/components/activities/activity-lifecycle?hl=ko

2. 자주 사용되는 생명주기 메소드

  1) onCreate

    - 엑티비티가 새롭게 시작되었을 때 내부 구문 실행

    - 주로 앱을 처음 실행했을 때 실행되는 구문들로 구성

    - 뷰 객체 생성 후 연달아 onStart와 onResume을 호출함

  2) onStart

    - 상호작용을 준비하는 단계

    - 곧 바로 onResume 호출

  3) onResume
    - 액티비티 새롭게 시작되고 상호작용을 받아들이는 가장 마지막 단계

    - 이벤트 수신, 사용자에게 보이는 동안 실행해야하는 모든 기능을 활성화 가능

    - 방해 동작이 수행되면 onPause를 호출

  4) onPause

    - 반투명 대화상자 등이 실행되면 메인 엑티비티가 일시정지상태가 됨 > 종료 시 onResume 호출

    - 백그라운드로 엑티비티가 이동하고 홈 화면으로가거나 다른 앱을 실행할 때도 거쳐감 > onStop 호출

  5) onStop

    - 모든 기능 일시정지

    - 정지 되어있는 동안은 모든 기능을 일시정지하고 필요하지않은 리소스를 해제 또는 조정 기능을 포함

    - 백그라운드에서 다시 실행될 때 onRestart 호출

    - 불필요한 리소스를 차지하는 앱을 죽이는 하드웨어 기능에 의해 shutdown된 경우 다시 실행될 때 onStart 호출 

  6) onDestory

    - 시스템에 의해 종료되거나 이벤트 수신으로 인해 종료된 경우 실행될 기능들로 구성

    - 소멸되기 전 모든 데이터를 정리해야함

  7) onRestart

    - 백그라운드로 엑티비티 이동 후 재개될 경우 호출되고 곧바로  onResume 호출

 

3. 임시 UI상태 및 복원

    - 엑티비티 이벤트 수신동안 얘기치 못한 종료나 시스템에 의해 램의 여유공간을 확보하기 위해 엑티비티를 강제종료되었을 때 데이터 손실을 막기 위해 임시 저장을 하고 이를 복원하는 기능을 구현해야함

    - 그러나 램의 많은 부분을 차지하므로 여러가지를 고려하여 구성해야 함

  1) 시스템의 엑티비티 종료 가능성

종료 가능성 프로세스 상태 엑티비티 상태
최소 포그라운드(포커스가 있거나 포커스를 가져올 예정) 생성(onCreate)
시작(onStart)
재개(onResume)
더보기 백그라운드(포커스 상실) 일시중지됨(onPause)
최대 백그라운드(보이지 않음) 중지됨(onStop)
최대 비우기 소멸됨(onDestroy)

 

  2) 인스턴스화

    - 사용자가 뒤로가기 버튼을 누르거나 엑티비티가 finish() 메소드를 호출하여 자체적인 소멸신화를 보내는 경우 모든 엑티비티 인스턴스에 관한 시스템과 사용자의 콘셉트가 모두 소멸된다. 그러나 시스템 제약에 의해 사라진 경우 인스턴스는 사라지더라도 시스템이 존재했다는 정보가 남아 다시 엑티비티로 돌아가기 위해 시도하면 소멸 당시의 상태를 설명하는 저장된 데이터 세트를 사용하여 해당 활동의 새로운 인스턴스를 생성한다. 시스템이 이전 상태를 되돌리기 위해 사용하는 저장된 데이터는 인스턴스 상태라고 하며 bundle 객체에 저장된 키-값 쌍의 모음이다. 

 

  3) UI 임시저장

    - 기본적으로 bundle 객체에 저장된 정보는 엑티비티 레이아웃의 View 객체 관련이며 시스템이 기본적으로 수행하는 것으로 별도의 코드 요청 없이 이전 상태로 복원된다. 단, 시스템이 엑티비티에서 뷰의 상태를 복원하기 위해서는 android:id 속성으로 제공되는 고유의 id가 각 뷰마다 할당되어야 한다.

    - Bundle 객체는 메인 스레드에 직렬화되어야하고 극소량의 데이터만으로 구성되어야한다. 이는 '영구 로컬 저장소', onSaveInstanceState() 메소드, ViewModel 클래스로 데이터를 보존하게 된다.

    - 기본적으로 사용자가 직접 엑티비티를 종료하거나 finish()메소드를 호출하여 엑티비티를 소멸한 경우 onSaveInstanceState()가 호출되지 않는다. 영구데이터를 저장하려면 엑티비티가 포그라운드에 있을 때, 최소한 onStop 상태일 때 저장되어야한다. 이외의 사용자가 얘기치 못하게 엑티비티가 소멸된 경우 onSaveInstanceState()메소드를 호출하며 bundle객체에 View계층 구조에 대한 임시정보를 저장한다.

 

  4) 저장된 인스턴스상태를 통한 UI 복원

    - 활동이 소멸된 후 재생성되면 시스템이 엑티비티에 전달하는 bundle로부터 저장된 인스턴스 상태를 복구할 수 있다. 주로 onCreate 및 onRestoreInstanceState() 콜백 메소드 둘 다 인스턴스 상태 정보를 포함한 동일한 bundle을 수신한다.

    - onCreate 메소드는 시스템이 엑티비티의 새 인스턴스를 생성하든, 이전 인스턴스를 재생성하든 상관없이 호출되므로 읽기 시도 전에 번들 상태가 null인지 확인해야한다. null인 경우 시스템은 이전에 소멸된 엑티비티의 인스턴스를 복원하지 않고 새 인스턴스를 생성한다. 

    - onRestoreInstanceState는 시스템이 onStart 메소드 다음으로 호출한다. 시스템은 복원할 저장 상태가 있을 경우에만     - onRestoreInstanceState를 호출하기 때문에 bundle의 null여부는 확인할 필요가 없다. 

 

4. 엑티비티의 전환

    - 앱은 생명 주기동안 여러번 들어가고 나올 가능성이 있으며 이 때에서 사용 중이던 상태의 UI를 임시로 저장해야할 상황이 발생한다.

  1) 다른 엑티비티에서 엑티비티 시작하기

    - 한 엑티비티의 생명주기 내에서 특정 시점에서 다른 엑티비티를 시작해야하는 경우, 엑티비티가 새로운 엑티비티의 결과를 받기를 원하는 지 여부에 따라 startActivity()나 startActivityForResult() 중 하나의 메소드를 사용하여 새 활동을 시작

    - 두 경우 다 마찬가지로 Intent 객체를 통해 정보를 주고 받는다.

  2) startActivity()

    - 새로 시작된 활동이 결과를 반환할 필요가 없을 경우 호출하는 메소드 

    - 다른 앱이 제공하는 기능을 사용할 때(예를 들어 이메일) 다음과 같은 코드를 통해 호출 가능

Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);

     - Intent 인스턴스를 생성하여 기능을 실어서 startActivity에 변수를 포함하여 호출하면 실행 가능, 이 때 상기한 대로 결과를 기존의 엑티비티에 반환하지 않는다.

  3) startActivityForResult()

    - 엑티비티가 종료될 때 결과를 받고자할 때, 예를 들어, 전화 앱에서 연락처 엑티비티를 통해 정보를 찾아 가져와 적용할 때 해당 메소드를 사용 (startActivityForResult(Intent, Int))

    - 결과는 onActivityResult(Int, Int, Intent)를 통해 반환된다.

    - 하위 엑티비티가 존재한다면 setResult(Int)를 호출하여 상위 활동으로 데이터를 반환할 수 있다.

  4) 엑티비티 조정

    - 엑티비티A와 B가 있다고 가정할 때 다음의 생명주기 단계를 거친다.

    - A의 onPause() 메소드 실행 > B의 onCreate, Start, Resume이 순차적으로 시작 > A가 더 이상 보이지 않은 경우 onStop 실행