2012년 6월 30일 토요일

Activity Life Cycle 알아보기


1. Activity Lifecycle

Activity Lifecycle이란!
액티비티의 시작, 실행, 활성, 비활성화, 정지, 종료되는 일련의 과정을 Activity Lifecycle이라고 한다.
어플리케이션의 액티비티가 포그라운드, 백그라운드 될 때 마다 상태가 끊임없이 변경이 된다.

액티비티는 스택에서 관리된다!
시스템의 액티비티들은 액티비티 스택에 의해 관리 된다. 새로운 액티비티가 시작되면 스택의 최상단에 놓여지게 되고 running 액티비티가 된다.
전의 액티비티는 스택에서 새로운 액티비티 아래에 놓여지게 된다. 그리고 새로운 액티비티가 존재할 때까지 포그라운드에 오지 않는다.
http://developer.android.com/guide/topics/fundamentals/tasks-and-back-stack.html 의 그림들만 보셔도 스택에서 관리가 되는지 명료하게 확인 가능 합니다. 


액티비티는 필수적으로 네 개의 상태가 있다.

<그림1 . Activity State>

- 액티비티가 스크린의 포그라운드(스택 최상단)에 있다면 active 또는 running 상태이다.
- 액티비티가 포커스를 잃는다면 그러나 아직 화면에 보여진다면(전체 화면이 아니거나 투명한 액티비티인 경우는 paused 상태이다. 
paused 액티비티는 완전히 살아있다.(모든 상태와 멤버 정보를 유지하고 window manager에 추가되어 남아있다.) 그러나, 극단적인 낮은 메모리 상황이 되면 시스템에 의해 죽여진다.
- 액티비티가 다른 액티비티에 의해 완전히 가려진 상태라면 stopped 된 것이다. 아직 모든 상태와 멤버 정보를 가지고 있다. 그러나 사용자에게 더 이상 보여지지 않고 window에 가려져 있고 메모리가 필요할 때 마다 시스템에 의해 killed 된다.
- 액티비티가 paused 또는 stopped 된다면 시스템은 finish를 요청하거나 단순히 프로세스의 killing에 의해 메모리로부터 액티비티를 죽을 수 있다. 다시 사용자에게 보여질 때, 완벽히 restart 그리고 이전 상태로 restore 되야 한다. 

Activity Lifecycle 이렇게 돌아갑니다. 



<그림2. Activity Lifecycle>

Lifecycle callback 메서드에 대해 알아봅시다.

(1) onCreate(Bundle savedInstanceState)
액티비티를 초기화한다. 중지했다가 재시작하면 액티비티의 이전 상태 정보인 Bundle이 전달된다.
Bundle에 따라 초기화가 다를 경우 onCreate()에서 Bundle 객체 받아 처리한다.

(2) onRestart()
재시작 될 때 호출된다.

(3) onStart()
액티비티가 사용자에게 보이기 직전에 호출된다.

(4) onResume()
사용자와 상호작용을 하기 직전에 호출된다.

(5) onPause()
다른 액티비티가 실행될 때 호출된다.
이 메서드가 리턴되어야 새 액티비티가 활성화된다.

(6) onStop()
액티비티가 사용자에게 보이지 않게 될 때 호출된다.
(7) onDestroy()
액티비티가 파괴될 때 호출된다.
시스템에 의해 강제 종료 여부는 isFinishing()메서드로 조사 가능하다.


(8) onSaveInstanceState(Bundle outputState)
강제종료시 호출된다. onPause()전에 호출된다.

(9) onRestoreInstanceState(Bundle savedInstanceState)
강제종료 후 다시 재시작 될 때 onResume() 전에 호출된다.
onStart()메서드 다음으로 호출되므로 필요한 모든 초기화가 완료된 후에 안전하게 복구할 수 있는 시점이다.



종료 형태에 따라 호출되는 메서드가 틀려져요!

(1) 정상종료
finish() 호출이나 Back 키를 누를 경우 사용자의 입력에 의한 작동이기때문에 정상적인 종료가 된다.

onPause() -> onStop() -> onDestroy()
onCreate() -> onStart() -> onResume() 

 (2) 강제종료
메모리 부족 현상이나 가로,세로 전환시 같은 강제적인 종료를 할 경우가 있다.
onSaveInstanceState()를 통해 임시적인 데이터를 Bundle 객체를 통해 저장한다.
onCreate()와 onRestoreInstanceState()를 통해 Bundle 객체를 가져온다.

onSaveInstanceState() -> onPause() ->onStop() -> onDestroy()
onCreate() ->onStart() ->onRestoreInstanceState() -> onResume()

<질문> Home 키를 누를 경우 onDestroy()가 안되고 onPause(), onStop()까지만 호출 됩니다. 왜 그럴까요? 


* 참고
Bundle
문자열로 된 키값과 임의 타입의 값을 저장하는 일종의 맵이다.

*참고 자료

* 참고 소스
 public class ActivityLifecycleExam1 extends Activity {

    private static final String TAG = "ActivityLifeCycle";
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(TAG, "onCreate()");
        if(savedInstanceState != null){
            String value = savedInstanceState.getString("state");
            Log.i(TAG, "state = " + value);
        }
        
        setContentView(R.layout.scrollbar1);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "onDestroy()");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.i(TAG, "onPause()");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.i(TAG, "onRestart()");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.i(TAG, "onResume()");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.i(TAG, "onStart()");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.i(TAG, "onStop()");
    }
    
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        Log.i(TAG, "onRestoreInstaceState()");
        if(savedInstanceState != null){
            String value = savedInstanceState.getString("state");
            Log.i(TAG, "state = " + value);
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Log.i(TAG, "onSaveInstanceState()");
        outState.putString("state", "ALIVE");
    }
}


마무리

액티비티 생명주기에 따라 각각의 메서드에서 처리해주어야 부분에 대한 이해가 확실해져야 합니다.
그리고 종료 방식에 따라 Bundle을 통해 데이터 처리 부분도 확실한 이해가 필요합니다.
직접 많은 코딩 훈련과 시행착오를 통해 확실히 이해하셨으면 합니다.
그럼 모두 열 코딩 하세요.^^



출처 : http://blog.daum.net/mellowwind/10853728

댓글 없음:

댓글 쓰기