액티비티 정지하기와 재시작하기(Stopping and Restarting an Activity)
액티비티(Activity)의 올바른 정지하기(stopping)와 재시작하기(restarting)는 사용자가 앱이 항상 살아있고 그들의 프로세스(process)를 잃지 않는 다고 인식하는 것을 보장하는데 있어서 가장 중요한 라이프사이클(lifecycle) 과정입니다.
여러분의 액티비티가 중지(stopped)되고 재시작(restarted)되는 몇가지 주요한 시나리오들(scenarios)이 있습니다:
° 사용자가 최근 사용앱 목록(Recent Apps windows)를 열고 여러분의 앱으로 부터 다른 앱으로 전환합니다. 현재 화면 전면(foreground)에 있는 여러분 앱의 액티비티는 정지(stopped) 됩니다. 만약 사용자가 홈 화면(Home screen) 런처 아이콘(launcher icon) 이나 최근 사용앱 목록(Recent Apps windows)을 통해 여러분의 앱으로 되돌아오면, 액티비티는 재 시작(restart) 됩니다.
° 사용자가 여러분의 앱안에서 새로운 액티비티를 시작하는 작업을 수행합니다. 두 번째 액티비티(Second Activity)가 생성될 때, 현재 액티비티는 정지(stopped) 됩니다. 만약 사용자가 Back 버튼을 누르고 나면, 첫 번째(First Activity)가 재 시작(restart) 됩니다.
° 사용자의 휴대전화에서 여러분의 앱을 사용하는 동안 전화를 수신합니다.
Activity 클래스는 여러분의 액티비티가 정지하고 다시시작할때 할 처리내용들을 작업할 수 있도록 onStop()과 onRestart()라는 2개의 라이프사이클(Lifecycle) 메소드를 제공합니다. 부분적으로 가려진 UI 장애물을 식별하는 paused 상태와 다르게, stopped 상태는 UI 가 더이상 보이지 않고 사용자의 포거스(focus)가 별도의 액티비티(또는 완전히 다른 앱)에 있다는 것을 보증합니다.
Note: stopped 될 때, 액티비티 인스턴스는 시스템 메모리안에 여전히 남아있기 때문에, 가능한 여러분은 onStop()과 onRestart()(onStart()도 역시)를 구현할 필요는 없습니다. 간단한 연산을 하는 대부분의 액티비티들은, onPause()를 사용해서 시스템 리소스들로부터 연결을 끊고 진행중인 동작들을 일시정지 하도록 하기에 액티비티의 stop과 restart는 잘 될 것입니다.
그림 1. 사용자가 액티비티를 떠날 때, 시스템은 액티비티를 멈추기 위해 onStop() 을 호출합니다.(1) 만약 사용자가 stopped 되어 있는 액티비티로 다시 돌아온다면 시스템은 onRestart()를 호출합니다.(2) 다음으로 빠르게 onStart()(3) 와 onResume()(4) 을 호출합니다. 시스템은 항상 onStop() 을 호출하기 전에 onPause()를 호출하기 때문에 무슨일이 있어도 액티비티가 정지되는 시나리오(scenario)는 발생하지 않습니다.
액티비티 정지(Stop your Activity)
----------------------------------
액티비티가 onStop() 메소드를 호출받았을 때, 그 것은 더이상 보이지 않기에 사용자가 사용하지 않는 동안 필요하지 않은 대부분의 리소스들은 릴리즈(release) 해야 합니다. 여러분의 액티비티가 stopped 되어 있을때, 시스템은 시스템 메모리의 복구가 필요할 때 액티비티 인스턴스를 파괴(destroy)할 지도 모릅니다. 극단적인 경우, 시스템은 여러분의 앱 프로세스(process)를 액티비티의 마지막 onDestroy() 콜백(callback) 호출 없이 죽여(kill) 버릴지도 모릅니다. 그래서 여러분은 메모리 누수(memory leak)를 일으키는 리소스들을 onStop() 을 사용하여 릴리지(release)해야 하는 것이 중요합니다.
비록 onPause() 메소드가 onSop() 메소드 전에 호출되더라도, 여러분은 onStop()을 사용하여 데이터베이스(database)의 저장(writing) 같은 CPU을 강하게 사용하는 큰 작업을 처리해야만 합니다.
예를 들어, 여기 영구적인 저장소에 노트 원고(draft note)의 내용물을 저장하는 onStop() 의 구현이 있습니다.
@Override protected void onStop() { super.onStop(); // Always call the superclass method first // Save the note's current draft, because the activity is stopping // and we want to be sure the current note progress isn't lost. ContentValues values = new ContentValues(); values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText()); values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle()); getContentResolver().update( mUri, // The URI for the note to update. values, // The map of column names and new values to apply to them. null, // No SELECT criteria are used. null // No WHERE columns are used. ); } |
여러분의 액티비티가 stopped 일때, Activity 객체는 메모리안에 여전히 거주하고 있고 액티비티가 resume 될때 다시 호출됩니다. 여러분은 Resume 상태로 읽어 올라가면서 호출되는 어떠한 콜백(callback)이 진행되는 동안에도 생성되어 있는 컴포넌트들(components) 을 다시 초기화할 필요는 없습니니다. 시스템은 또한 레이아웃(layout)안에 있는 각 각의 View에 대한 현재 상태와 진행사항을 유지하고 있습니다.그렇기에 사용자가 EditText 위젯(widget)안에 작성했던 텍스트(Text) 내용물(contents)은 여러분이 별도의 저장이나 읽기를 할 필요없이 메모리에 남아있습니다.
Note : 심지어 시스템이 액티비티가 stopped 된 상태에서 파괴(destroy)하더라도, View( EditText안에 있는 text ) 의 객체 상태는Bundle(key-value 쌍의 덩어리(blob))안에 여전히 남아있으며, 사용자가 같은 액티비티의 인스턴스로 되돌아 온다면 그 것들을 다시 읽어들입니다.( 다음 시간에 액티비티가 파괴(destroy)되고 다시 생성(recreate)할 경우 Bundle 을 사용하여 다른 상태 데이터(data)를 저장하는 것에 대해 알아보겠습니다.)
액티비티의 시작/재시작 ( Start / Restart Your Activity)
-----------------------------------------------------
여러분의 액티비티가 stopped 상태에서 화면 전면(foreground)로 돌아 올 때, onRestart()의 호출을 받게 됩니다. 시스템은 또한 액티비비티가 화면에 보이기 시작하는(처음 만들어지든 다시 시작하든) 매 순간마다 발생하는 onStart() 메소드도 호출합니다. 어쨋든, onRestart()메소드는 오직 액티비티가 stopped 상태에서 resume 될 때만 호출되어 집니다. 그래서 파괴(destroy) 되지 않은 액티비티가 stopped 되기 이전의 상황으로 필요하다면 다시 읽어들이는 작업을 수행할 수 있습니다.
액티비티의 상태를 읽어들이기 위해 onRestart()를 사용하는 것은 매우 드문 일입니다. 그래서 일반적인 앱들에게 이 메소드를 적용하는 것에 대해서는 어떠한 가이드라인(guideline)도 없습니다. 어쨋든 여러분의 onStop() 메소드는 근본적으로 모든 액티비티의 리소스들을 깔끔하게 제거하도록 되어 있기 때문에, 여러분의 액티비티가 다시 시작할 때 그 것들을 다시 인스터스화 할 필요가 있습니다. 아직 여러분은 액티비티를 처음 생성할 때(액티비티의 인스턴스가 존재하지 않을 때) 그 것들을 인스턴스화 할 필요가 있습니다. 시스템은 여러분의 액티비티가 처음 만들어 질때와 stopped 상태에서 다시 시작할 때의 둘 모두에서 onStart()를 호출하기 때문에 이번시간에 여러분은 onStop() 메소드의 대응 상황으로 onStart() 콜백(callback) 메소드를 사용하도록 합니다.
예를 들어, 사용자가 오랫동안 떠나 있다가 액티비티로 다시 돌아올 수도 있기 때문에, onStart() 메소드는 시스템 기능들이 사용되는지 확인하는 좋은 위치가 됩니다.
@Override protected void onStart() { super.onStart(); // Always call the superclass method first
// The activity is either being restarted or started for the first time // so this is where we should make sure that GPS is enabled LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!gpsEnabled) { // Create a dialog here that requests the user to enable GPS, and use an intent // with the android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS action // to take the user to the Settings screen to enable GPS when they click "OK" } } @Override protected void onRestart() { super.onRestart(); // Always call the superclass method first
// Activity being restarted from stopped state } |
시스템은 여러분의 액티비티를 파괴(destroy)할 때, 액티비티의 onDestroy() 메소드를 호출합니다. 일반적으로 여러분은 onStop()에서 대부분의 리소스들을 릴리즈(release) 하기 때문에 onDestroy() 호출을 받을 때, 대부분의 앱이 해야할 일이 더 이상 없습니니다. 이 메소드는 려어분이 메모리 누수(memory leak)를 일으키는 리소스들에 대해 제거할 수 있는 마지막 기회입니다. 그렇기에 여러분은 추가적으로 스레드들(Threads)이 파괴되었는지 다른 장기 실행 작업이 중지되어 있는지 확인해야 합니다.