Android LifeCycle
업데이트:
카테고리: Android
/태그: adb, LifeCycle, LifeCycleObserver, logging, Timber
LifeCycle
유저가 앱을 시작하고, 사용하고 다시 종료하면 Activity
인스턴스는 수명주기 안에서 서로 다른 상태를 통해 전환된다.
이런 라이프사이클을 잘 정의해두면 다음과 같은 오류를 예방할 수 있다.
- 앱을 사용하던 도중에 전화가 걸려오거나 다른 앱으로 전환할 때 비정상적으로 종료되는 문제
- 앱을 잘 사용하지 않는 경우 시스템 리소스가 소비되는 문제
- 앱에서 나갔다가 돌아왔을 때 진행상태가 저장되지 않는 문제
- 화면이 가로 방향, 세로 방향으로 전환될 때 비정장적으로 종료되거나 진행상태가 저장되지 않는 문제
Acivity LifeCycle
-
OnCreate()
시스템이 구동될 때 먼저 실행되는 것으로 필수적으로 구현해야 한다.
전체 라이프사이클 중 한 번만 발생한다.예를 들어 데이터를 목록에 바인딩하고, Acivity를 연결하고, 클래스를 인스턴스화 할 수 도 있다.
-
OnStart()
활동이 시작된 상태에 들어가면 이 메서드를 호풀한다.
OnStart
가 호출되면 할동이 사용자에게 표시되고, 앱은 활동을 포그라운드에 보내 상호작용을 준비할 수 있도록 한다.포그라운드
: 앱이 켜져 있는 상태, 유저가 앱을 사용하고 있는 상태백그라운드
: 앱이 꺼져있거나, 앱을 사용하다가 홈 버튼을 사용하여 빠져나온 경우 -
onResume()
활동이 재개됨 상태에 들어가면 포그라운드에 표시되고onResume()
을 호출한다.
어떤 이벤트가 발생하여 앱에서 포커스가 떠날 때까지 앱이 이 상태에 머무른다.
예로 전화, 다른 앱으로 이동, 화면 꺼짐… 이 있다. -
onPause()
사용자가 활동을 떠날때 첫번째 신호로 이 메서드를 호출한다.
활동이 더이상 포그라운드에 있지 않는다.
작업을 일시중지하거나 조정한다.활동이 일시중지 중이고, 유저가 필요하지 않을 때 배터리에 영향을 주는 요소를 해제할 수 도 있지만 멀티윈도우 모드에서는 보이게 되기 때문에
onStop()
을 사용하는 것이 좋다.주의
이 메서드는 아주 잠깐 실행되므로 저장 작업을 실행하기에는 시간이 부족할 수도 있다.
그래서onPause()
로는 데이터 저장, 네트워크 호출, 데이터베이스 트랜잭션을 실행해서는 안된다
이런것은onStop()
에서 사용하는 것이 적절하다. -
onStop()
활동이 유저에게 더이상 표시되지 않으면 중단됨 상태에 들어가고 해당 메서드를 호출한다.onPause
대신onStop
사용하면 사용자가 멀티 윈도우 모드에서 활동을 보고 있어도 UI 관련 작업이 계속 진행된다.해당 상태에 들어가면
Activity
객체는 메모리 안에 머무르게 된다. 재실행하였을 때 해당 정보가 남아있으므로 다시 불러올 필요가 없다.다시 시작되면
onRestart()
를 호출하고 실행을 종료하면onDestory()
를 호출한다. -
onDestroy()
활동이 소멸되기 전에 호풀한다.- 유저가 앱을 닫거나,
finish()
가 호출되어 종료되는 경우 - 구성변경(기기 회전, 멀티윈도우)으로 인해 시스템이 일시적으로 활동을 소멸시키는 경우
구성변경이 일어난 경우
ViewModel
은 그대로 보존되어 다음 활동 인스턴스에 전달되므로 추가적인 작업이 필요없다.앱이 종료되었을 때는,
onCleared()
를 호출하여 데이터를 정리해야한다. - 유저가 앱을 닫거나,
Fragment LifeCycle
살펴보면 activity의 라이프 사이클과 유사하지만 Create와 Destory 중간에 onViewCreated
, onViewStateRestored
, onSaveInstanceState
, onDestoryView
가 추가되어 있다.
-
onViewCreated
onCreateView의 반환값으로 정상적인 FragmentView 객체를 제공하였을 때 해당 메서드가 실행된다.Fragment의 초기값을 설정하거나, LiveData 옵저빙… 을 해당 메서드에서 실행하는것이 적절하다.
-
onViewstateRestored
저장해둔 모든 State 값이 Fragment View 계층구조에 복원 되었을 때 호출된다.예를 들면 체크박스 위젯이 현재 체크 되어있는 등 뷰의 상태값을 확인할 수 있다.
-
onSaveInstanceState
Fragment에 저장된 데이터가 사라지지 않도록 저장할 수 있게 하는 메서드이다. -
onDestoryView
Fragment가 화면으로부터 벗어났을 때 Fragment의 라이프 사이클은 사라지고onDestory
가 호출된다.
Logging
LifeCycle Method애 Log.i()
를 입력하여 해당 메서드가 실행하였는지 Logcat에서 확인할 수 있다.
Timer를 사용하기
Log와 같이 로그를 남기는 라이브러리이다.
Log와 달리 tag를 필수로 작성할 필요가 없다.
- Module에 의존성 추가
dependencies { ... implementation 'com.jakewharton.timber:timber:4.7.1' }
- 새로운 클래스 제작하기
class ClickerApplication : Application() { override fun onCreate() { super.onCreate() Timber.plant(Timber.DebugTree()) } }
Log대신 Timber를 사용하여 로그를 남길 수도 있고
Timber.plant()
로 특정 상태에서만 로그를 남길수도 있다.작성한 클래스는
AndroidManifest.xml
에 추가해준다.<application android:name=".ClickerApplication" ...
단 이렇게 Manifest에 추가했을 경우 더이상 Log는 사용이 불가하니 주의하도록 하자
화면을 뒤로가거나 홈버튼으로 이동시
onPause
,onStop
메서드가 실행되고 다시 앱으로 돌아돌아오면onRestart
,onStart
,onResume
메서드가 실행된다. 처음 앱이 구동될 때는onCreate
메서드가 실행되고 이후 앱을 다시 접속하면onRestart
가onCreate
와 같이 작동되게 된다. 아예 앱을 종료 시켜버릴 때onDestory
가 실행된다.공유가 같이 앱내에서 다른 앱을 구동시키면
onStop
이 아닌onPause
가 걸리게 된다.
LifecycleObserver
기본적으로 lifecycle 메서드를 실행시키기 위해서는 사용하는 메서드를 다 입력해야 되기 때문에 호출이 너무 많이 발생하게 된다.
Lifecycle
은 구성요소의 lifecycle에 관한 상태 정보를 다른 객체가 관찰할 수 있도록하는 클래스이다.
사용은 해당 클래스가 만들어질 때 lifecycle.addOberser()
로 다른 객체가 관찰할 수 있게 만든다.
class DessertTimer(lifecycle: Lifecycle) : LifecycleObserver {
init {
lifecycle.addObserver(this)
}
그러고 lifecycle에서 호출할 함수 위에 @OnLifecycleEvent(Lifecycle.Event.ON_START)
를 추가하여 이 함수가 어떤 상태에서 호출되야하는지 알려준다.
클래스를 만들때 인자로 lifecycle을 넘겨준다.
dessertTimer = DessertTimer(this.lifecycle)
시뮬레이터 정지
adb shell am kill com.example.android.dessertclicker
deseertclicker의 패키지가 실행중인 기기나 에뮬레이터에 멈추라는 메세지를 보낸다.
adb 명령어를 찾을 수 없음
-
안드로이드 스튜디오 - Settings - Appearance & Behavior - System Settings - Android SDK
sdk의 설치된 경로를 복사한다. -
시스템 환경변수에서 시스템 변수 새로만들기
이름 : ANDROID_HOME / 경로 : 1번에서 찾은 경로 -
시스템 변수의 Path를 클릭하여 새로운 변수 생성
%ANDROID_HOME%\platform-tools
데이터 저장하기
onSaveInstanceState()
는 앱을 제거할 때 데이터가 저장하기 위해서 사용하는 메서드이다.
해당 메서드는 onStop
이 작동된 후 실행된다.
홈버튼을 누르면 해당 메서드가 실행되는 것을 확인할 수 있다.
데이터는 어떻게 저장되나
outState.put(변수이름, 값)
으로 Bundle에 저장된다.
앱 재실행
onCreate
는 Bundle
을 실행할 때마다 가져온다.
만약 앱을 중지시켰다가 재실행하는 경우에는 내가 저장한 bundle이 onCreate
에 넘어가게 된다.
그렇기 때문에 처음 실행시 onCreate
의 Bundle은 null
이 된다. 그래서 재실행 여부를 확인하기 위해서는 Bundle의 값이 들어있나 확인하면 된다.
if (savedInstanceState != null) {
revenue = savedInstanceState.getInt(KEY_REVENUE, 0)
}
저장된 값이 null
이 아니라면 저장되어 있는 값을 가져온다.
가져올 때 넣을 때와 동일한 키값이 필요하다.
인자로 키와, 기본값을 입력하면 저장된 값을 가져올 수 있다.