태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

액티비티의 생애주기(Lifecycle)

2009.09.18 04:45

안드로이드는 모바일 기기에서 구동되는 것을 목적으로 하고 있기에 PC에서 구동되는 프로그램들에 비해 더 효율적인 메모리 관리가 필요합니다. 

안드로이드 어플리케이션을 구성하는 구성요소 중 하나인 액티비티(Activity)도 효율적인 메모리 관리를 위해 액티비티가 생성되고 소멸되는 조건인 생애주기(Lifecycle)을 가지고 있습니다. 액티비티 뿐만 아니라 브로드캐스트 리시버(Broadcast Receiver), 서비스(Service)도 일정한 생애주기를 갖고 있지만, 가장 자주 쓰이는 구성요소인 액티비티의 생애주기부터 알아보도록 하겠습니다.

액티비티의 상태는 크게 활성(Active), 일시정지(Paused), 정지(Stopped) 이 3가지로 나눌 수 있으며, 각 상태에 해당하는 생애주기들이 존재합니다. 우선, 액티비티의 상태에 대해 알아보도록 하겠습니다.

  • 활성(Active)
    현재 화면에 액티비티가 표시되는 상태이며, 사용자와 상호작용(버튼을 누르거나 글자를 입력하는 등..)을 할 수 있는 상태를 말합니다. 일반적으로 액티비티가 화면에 표시되고 있을 때 액티비티는 활성 상태입니다.

    액티비티 내의 EditText 위젯에 텍스트를 입력하는 등, 사용자와 상호작용이 가능합니다.



  • 일시정지(Paused)
    화면에서 액티비티가 보이지만, 사용자와 상호작용은 할 수 없는 상태입니다. 즉, 배경이 투명한 액티비티나 화면 전체를 가리지 않는 다른 액티비티에 의해 액티비티의 일부가 가려진 경우가 해당됩니다. 다이얼로그 또한 액티비티의 일부를 가리지만, 다이얼로는 액티비티의 일부이기 때문에 이 때에는 일시정지 상태로 바뀌지 않습니다.

    다이얼로그가 화면을 가린 경우에는 Paused 상태가 되지 않습니다.

    배경이 투명한 액티비티가 화면을 가린 경우 가려진 액티비티는 Paused 상태가 됩니다.

     
  • 정지(Stopped)
    다른 액티비티에 의해 완전히 가려진 상태입니다. 액티비티 A가 액티비티 B를 호출해서 액티비티 B가 화면에 표시된 경우, 액티비티 A의 모습은 화면에서 더이상 보이지 않게 되겠지요? 따라서 액티비티 A는 정지 상태가 됩니다.


액티비티의 상태는 위와 같이 크게 3가지로 나뉘지만, 안을 살펴보면 아래와 같이 7개의 상태로 나눠지게 됩니다. 아래의 메소드들이 호출됨에 따라 액티비티의 상태들이 바뀌게 되며, 액티비티를 구현할 때 해당 메소드를 오버라이드한 후 각 상태에 따라 처리해줄 작업을 지정해주면 됩니다.

  • void onCreate(Bundle savedInstanceState)
  • void onStart()
  • void onRestart()
  • void onResume()
  • void onPause()
  • void onStop()
  • void onDestroy()

액티비티 생애주기(Activity Lifecycle)



위 메소드들의 이름을 통해 onCreate, onStart.. 등 이 메소드들이 호출되는 조건들을 어렴풋이 짐작할 수 있습니다. 하지만 어렴풋이 아는 것 만으로는 안되겠죠?

액티비티는 액티비티의 생애주기에 따라 상태가 변하게 되는데, 액티비티의 상태를 변화시키기 위해 각 상태에 해당하는 메소드가 호출됩니다. 따라서, 어플리케이션을 작성할 때 액티비티의 생애주기에 따라 알맞는 작업을 처리해주기 위해 각 상태에 해당하는 메소드를 오버라이드하여 처리할 작업을 넣어주게 됩니다. 

예를 들면, 데이터베이스를 사용하는 어플리케이션에서는 메인 액티비티가 실행될 때 데이터베이스를 열고 사용할 준비를 해야 합니다. 그리고, 데이터베이스를 사용하는 액티비티가 소멸될 때에는 사용하던 데이터베이스를 닫아줘야 합니다. 만약 이러한 작업을 적절히 처리해주지 않으면 데이터베이스를 닫아주지 않아 에러가 발생하는 등 여러가지 문제가 생길 것입니다.

그럼, 액티비티의 생애주기 내에서 액티비티의 상태가 어떻게 변하는지, 어떤 메소드가 호출되면 액티비티의 상태가 변하게 되는지 알아보도록 합시다.


액티비티의 시작


액티비티를 처음 시작하려면, 액티비티를 만들어 줘야겠지요? 객체를 사용하려면 객체의 생성자를 이용하여 새로운 인스턴스를 만들어주듯이, 액티비티 또한 이러한 과정이 필요합니다.

액티비티의 생성은 onCreate(Bundle savedInstanceState) 메소드가 호출을 통해 이루어집니다. 액티비티가 생성되니까 onCreate()메소드가 호출되는 것은 알겠는데, 인자로 받는 savedInstanceState는 뭔지 잘 모르겠다구요? - 요놈은 잠시 후에 설명할테니, 궁금해도 조금만 참아주세요. ^^;

onCreate() 메소드에서는 액티비티의 "초기화"를 담당하는 코드들을 처리해줍니다. 액티비티에서는 기본적으로 각종 버튼이나 리스트, 체크박스, 입력 표시줄(EditText) 위젯들이 배치되어 있는 레이아웃을 구성하므로, 그러한 위젯들이 사용자와 상호작용을 할 수 있도록 해주는 코드들을 담고 있어야 합니다. 예를 들면, 버튼을 누르면 다른 액티비티가 뜨게 하거나, 아니면 입력 표시줄(EditText)에서 받은 데이터를 처리하는 것 등이 될 수 있겠죠.

onCreate() 메소드를 통해 액티비티를 시작하기 위한 준비를 모두 끝마쳤다면, 액티비티를 시작해야겠지요? 액티비티의 시작은 onStart() 메소드를 통해 이루어집니다. 하지만, 이 상태는 완전히 액티비티가 시작된 상태가 아니라 액티비티가 화면에 표시되기 "직전"의 상태입니다. 이어서 onResume()메소드가 호출되면 액티비티가 화면에 표시되고, 사용자와 상호작용을 하기 직전의 상태가 됩니다. 액티비티가 생성된 후 바로 액티비티를 실행하면 간단할 것 같은데, 왜 굳이 복잡하게 onStart()onResume()으로 나누었을까요? 


onStart()와 onResume()의 비교

 
액티비티 생애주기 그림을 다시 보도록 하죠. onStart()onResume()의 위치가 다른 것을 볼 수 있습니다.

onStart()는 액티비티가 실행되다가 다른 액티비티가 화면에 표시되어 정지 상태가 되면서 onStop()이 호출되었다가, 메모리에서 사라지기 전에 다시 정지되었던 액티비티가 호출되어 onRestart()를 거쳐 오거나, 혹은 메모리가 부족하여 프로세스가 종료되었다가 다시 액티비티를 생성하고, (onCreate() 호출) 액티비티를 화면에 표시하면서 onStart()를 호출하게 됩니다. 즉, onStart()에서는 정지(Stopped) 상태에서 액티비티가 복귀될 때 호출된다고 할 수 있습니다. 이는 한마디로 액티비티가 화면에서 보이지 않다가 다시 나타나는 것을 의미합니다.


반면, onResume()은 액티비티가 일시정지(Paused) 상태에서 복귀될 때 호출됩니다. 즉, 이는 액티비티가 사용자와 상호작용을 하지 못하다가 다시 상호작용을 할 수 있게 되는 것을 의미합니다.

이렇게, 액티비티가 대기 상태에 있다가 복귀되는 시점 및 복귀되는 기능이 다르기 때문에 onStart()onResume()처럼 시작 과정이 복잡하게 나누어져 있는 것입니다.

액티비티의 정지/일시정지


액티비티가 화면에 표시되고, 사용자와 상호작용을 할 수 있는 활성(Active)상태에서 다른 액티비티에 의해 가려지거나, 화면에서 사라지게 되면 그 액티비티는 정지(Stopped) 상태가 됩니다. onStop()메소드가 호출되면 해당 액티비티는 정지 상태가며, 이곳에서부터 액티비티의 운명은 갈리게 됩니다.




일반적으로 정지된 액티비티는 사용자가 다시 사용할 것을 대비하여 메모리서 바로 사라지지 않고 올라가 있다가 메모리가 부족하게 되면 메모리 확보를 위해 강제로 종료되게 되죠. 그 후, 사용자가 다시 그 액티비티를 실행시키게 되면 다시 액티비티를 생성한 후(onCreate() ) 액티비티를 실행시키게 됩니다. 반면에, 메모리 부족 등이 발생하지 않아 액티비티가 대기 상태로 메모리에 올려져 있을 때 다시 그 액티비티를 호출하게 되면 액티비티를 다시 만들 필요 없이 다시 화면에 표시하면(onRestart()) 되므로, 액티비티를 다시 시작하기만 하면 됩니다.

액티비티가 일시정지(Paused)되는 것은 액티비티가 화면에는 표시되고 있지만, 사용자와 상호작용을 하지 않아서입니다. 일시정지 상태에는 이것 외에도 중요한 것이 하나 더 있습니다. 위의 생애주기에서도 확인할 수 있듯이, 일시정지 상태에서도 메모리가 부족하면 액티비티가 종료될 수 있습니다. 

일시정지 상태에서는 대부분 사용자가 어떤 내용을 입력하고 있는 등, "어떠한 작업이 진행 중"일 가능성이 높습니다. 그런데, 메모리가 부족해 액티비티를 종료시키게 된다면 사용자가 입력했던 데이터들 (예:작성중이던 메시지 등..)이 손실됩니다.

이를 방지하기 위해 메모리 부족 등으로 "어쩔 수 없이" 액티비티를 종료해야 하는 경우 onSaveInsstanceState() 메소드가 호출되며 액티비티의 상태를 Bundle 형태로 저장하게 됩니다. 따라서, onSavedInstanceState() 메소드는 항상 호출되지 않으며, 만약 호출된다면 프로세스가 종료되기 전, onPause() 이후 혹은 onStop() 이후에 호출될 수 있습니다. 

onSaveInstanceState() 메소드를 통해 저장된 상태는 Bundle 객체 형태로 저장되어 있다가, 나중에 해당 액티비티를 다시 실행할 때 onCreate()메소드 및 onRestoreInstanceState()메소드에서 액티비티가 강제로 종료될 때의 상태로 액티비티를 복원하게 됩니다. 

onCreate() 메소드와 onRestoreInstanceState() 모두 Bundle 객체를 인자로 받고 있으며, 실제로 액티비티가 강제 종료될 때 저장된 상태정보가 담겨있는 Bundle 객체의 정보를 동일하게 전달받게 됩니다. 따라서 액티비티 상태의 복구는 두 메소드 모두에서 처리해줄 수 있으며, 상황에 따라 적합한 메소드에서 상태를 복원해주는 코드를 넣어주면 됩니다.
onRestoreInstanceState() 메소드 역시 항상 호출되는 메소드는 아니며, 호출된다면  onCreate() 메소드 이후에 호출되게 됩니다.

즉, 위의 두 메소드는 액티비티가 "강제로" 종료되었을 때 혹은 그 후 액티비티를 다시 실행시킬 때만 실행되므로, 만약 액티비티가 시작하고나 종료될 때 해 주어야 할 작업이 있다면 저 두 메소드를 오버라이드하는 대신 onCreate(), onStop() 및 onDestroy()메소드를 오버라이드한 후 그 안에 코드를 구현해야 안정적으로 해당 작업을 처리하줄 수 있습니다.

아래에 액티비티 생애 주기를 구성하는 주요 메소드의 역할을 간단히 정리해 보았습니다.



저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

커니 어플리케이션 구성/액티비티(Activity) , , , , , , ,

  1. Blog Icon
    정재현

    참 좋은글이 많네요

    항상 많은 공부를 하고 있습니다.

    시간이 되시면 책을 한권 안드로이드로 내주시면 감사하겠습니다 ^^

  2. 현재 열심히 원고 쓰고있답니다 :)
    조만간에 찾아뵐테니 한권 사주세요 :)

  3. Blog Icon
    자바맨

    설명히 쉽게 잘 되있네요^^
    어플 개발 공부에 도움이 많이 될 것 같아요 ㅎ

  4. Blog Icon
    카리만

    흠.. 설명이 좀 헷갈리는 부분이 있어서 질문 드립니다.

    "액티비티의 시작은 onStart() 메소드를 통해 이루어집니다. 하지만, 이 상태는 완전히 액티비티가 시작된 상태가 아니라 액티비티가 화면에 표시되기 "직전"의 상태입니다" 라고 설명에 나와 있는데, 다시 바로 밑에 그림에서는 액티비티를 화면에 표시한다라고 나옵니다. 이게 헷갈리네요+_+;;;;

  5. 액티비티가 화면에 표시되기만 하고, 상호작용이 시작되지 않은 상태를 뜻합니다 :) (화면 터치 등의 동작 불가)

  6. Blog Icon
    생각+

    다른곳(사이트, 서적) 에서 찾아보기 어려운 상세한 설명이 참 좋네요
    출판하시면 꼭 사도록 하겠습니다
    근데 언제쯤 출판예정 이신가요?...

  7. 아마 멀지 않은 시일에 나오지 않을까 싶습니다 ㅎㅎ
    자세하게 날짜가 나오게 되면 공지 띄워드릴께요 :)

  8. Blog Icon
    바나나맛우유조아

    커니님 강좌는
    바나나맛우유보다 더 맛있는 맛이라고 할까??
    표현이 안되네요 ㅎ

  9. Blog Icon
    소스는 없나요 ㅠㅠ

    음... 정말 이해는 쏙쏙 가는데.. 응용이란.. 참;; 그렇죠 ㅠㅠㅠ 혹시 예제 소스를 좀 구할수 없을까요 ㅠ?
    지금 제 소스라도 좀 봐주세영

    public void onPause() {// 홈키를 눌려서 나가면 종료된 뒤에 나갈수 있게 도와줌
    super.onPause();
    onRestart();
    }
    public void onRestart() {
    super.onRestart();
    onStart();
    }
    public void onStart() {

    super.onStart();
    setContentView(new Panel(this));
    }
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    onStart();
    }
    다시 실행 되게 하려면 어떻게 해야 할까요? 일시정지후에 ! 계속 에러가 뜨네요 홈키 눌리면

  10. 생애주기 메서드를 강제로 호출하는 것은 잘못된 방법입니다.
    이 메서드들은 액티비티 상태가 변경될 때 호출되는 콜백 메서드이지, 강제로 호출하는 메서드가 아닙니다. 이 메서드를 호출한다고 해서 액티비티 상태가 바뀌는 것도 아니구요.

    홈키를 눌렀을 때 액티비티를 종료해야 한다면, onStop() 메서드에서 finish()를 호출하여 액티비티를 명시적으로 종료하는 방법을 사용하면 될 것 같군요.

  11. Blog Icon
    고갑천

    좋은 정보 감사합니다. 유용하게 쓰겠습니다^^

  12. Blog Icon
    김섭

    OnCreate 부분을 한 자바파일에서 두가지 사용하고싶은데 OnCreate1,OnCreate, 이렇게 두가지로 사용하여도 무방한가요?

  13. 상태에 따라 할 작업을 두 가지로 나누어 한다는 것인지, 아니면 onCreate() 의 동작 자체를 바꾼다는 것인지 잘 모르겠습니다.

    전자라면 굳이 onCreate1() 이런 식의 네이밍이 아니라 실질적으로 수행하는 역할을 표현할 수 있는 이름으로 메소드를 작성하면 될 것이고, 후자의 경우 onCreate() 를 오버라이드 한 후 super 메서드를 호출하지 않으면 되지만 액티비티가 제대로 동작하지 않을 것입니다.