yourginieus
Life Cycle 및 Logging - Timber 본문
LifeCycle
- 모든 activity와 fragment는 생명주기를 가짐
- Activity의 lifecycle은 액티비티가 최초로 초기화되었을 때부터 최종적으로 파괴되었을 때까지, 그리고 시스템에 의해 메모리가 회수될 때까지 액티비티가 통과할 수 있는 다양한 상태로 구성 됨
- 사용자가 앱을 시작하고, activity 사이를 이동하고, 앱 내부와 외부로 이동하고, 앱을 종료하면 activity의 state 가 변경됨
- 이러한 state는 activity의 status를 나타냄

- Activity lifecycle 상태가 변경될 때 일부 동작을 변경하거나 코드를 실행해야 하는 경우가 많음
- 그래서 Activity 클래스 자체는 물론 AppCompatActivity 같은 하위 클래스도 모두 set of lifecycle callback method 를 가지고 있음
- Android는 Activity가 한 state에서 다른 state로 이동할 때 이러한 콜백을 호출하며, 사용자는 자신의 activity에서 이러한 methods를 override하여 lifecycle 상태 변화에 대응하는 작업을 수행할 수 있음

- 이러한 콜백이 호출되는 타이밍과 각 콜백 방식에서 무엇을 해야 하는지 아는 것이 중요함!
STEP 1 : onCreate() method를 조사하고 logging 추가
- Android 생명주기에 무슨 일이 일어나고 있는지 알기 위해서는 다양한 생명주기 method가 호출되는 시기를 알면 도움이 됨
- 이를 위한 간단한 방법은 logging API를 사용하는 것! 로깅을 사용하면 앱이 실행되는 동안 콘솔에 짧은 메세지를 쓸 수 있으며, 이를 사용하여 다른 콜백이 호출되는 시기를 표시할 수 있음
- 위의 다이어그램에서, onCreate()을 사용한 적이 있기 때문에 좀 익숙할 것!
- 모든 activity가 구현해야 하는 유일한 method
- onCreate() method는 Activity에 대해 일회성 초기화를 수행하는 곳
- 레이아웃을 inflate하거나, click listener를 정의하거나, data binding을 설정하는 등
- onCreate() 생명주기 함수는 액티비티가 초기화(initialized)(새로운 액티비티 object가 메모리에 생성됨) 된 직후에 닥 한 번 호출 됨
- onCreate()의 실행이 끝나면, activity는 생성된 것으로 간주됨

**onCreate()는 override 된 것이므로 super.onCreate() 필수임!
- onCreate method 에서 super.onCreate() 바로 다음 줄에 Log 출력 추가
override fun onCreate(savedInstanceState: Bundle?) {
...
Log.i("MainActivity", "onCreate Called")
}
Log 메세지의 중요도
- Log.i() : informational message
- Log.e() : errors
- Log.w() : warnings
* Tag(위에서는 "MainActivity") 는 Logcat에서 로그 메세지를 더 쉽게 찾을 수 있는 문자열. 일반적으로 클래스의 이름임
* 뒤 쪽의 문자열이 실제 로그 메세지
STEP 2 : onStart() method 구현
- onStart() 생명주기 함수는 onCreate() 직후에 호출됨
- onStart()가 실행되고 나면 Activity가 회면에 표시됨
- 액티비티 초기화를 위해 오직 한 번만 호출되는 onCreate() 와는 달리, onStart()는 activity lifecycle 동안 여러 번 호출될 수 있음

- onStart()는 onStop() 과 짝을 이룸!
- 사용자가 앱을 시작한 후 디바이스의 홈 화면으로 돌아가면, activity는 작업이 중지되고 화면에 더 이상 표시되지 않음
override fun onStart() {
super.onStart()
Log.i("MainActivity", "onStart Called")
}
- 디바이스의 홈 버튼을 누른 다음 최근 화면을 이용해 Activity로 되돌아간다면,
- Activity가 종료된 곳에서 모두 같은 값으로 resume 되고, onStart()는 Logcat에 기록 됨( 처음 앱 실행에 이어서 두 번째로 기록 남는 거!)
- 단, onCreate()는 보통 다시 호출되지 않음!
STEP 3 : onResume()
- activity에 focus를 맞추고, 사용자가 activity와 상호작용할 수 있도록 준비함
- startup 시 호출됨. -> 재개하는 경우가 아닌 경우에도 일단 시작하기만 하면 호출 됨!

STEP 4 : onDestory()
- 액티비티가 완전히 shut down(closed) 되어 garbage-collected를 검출할 수 있음을 의미함
- garbage-collection : 더 이상 사용하지 않을 objects의 자동 정리
- onDestory()의 호출 이후에는, OS는 이러한 리소스를 폐기할 수 있음을 알고 해당 메모리를 청소하기 시작함

- code로 액티비티를 finish() 하거나, 앱을 강제종료하는 경우에도 activity가 완전히 종료될 수 있음!
- Android system은 앱이 오랫동안 화면에 나타나지 않으면 이 또한 자동으로 작업을 종료할 수 있음
- Android는 이를 통해 배터리를 보존하고 앱의 리소스를 다른 앱에서 사용할 수 있도록 함
- onCreate()와 onDestroy()는 하나의 activity의 lifecycle 동안 오직 1번씩만 호출됨
- onCreate() 는 앱을 초기화하고, onDestroy() 는 앱에서 사용하는 리소스를 정리함
STEP 5 : onPause() & onStop()
- 사용자가 액티비티에서 벗어날 때마다 액티비티가 완전히 종료되는 것은 아님!
- 액티비티가 화면에 더 이상 표시되지 않는 경우
- = activity를 background로 되돌리는 것 (이것의 반대는 액티비티가 foreground 또는 화면에 있는 경우)
- 사용자가 앱으로 돌아오면 동일한 작업이 다시 시작되고 표시됨
- lifecycle의 이 부분을 app's visible lifecycle이라고 함
- background에 있는 앱은 시스템 리소스와 배터리 수명을 유지하기 위해 실행 중이 아니어야 함
- Activity의 lifecycle을 이용하여 내 앱이 언제 background로 가는지 알아내서 진행 중인 작업을 pause 할 수 있음
- 그런 다음 앱이 화면에 뜨면 이러한 작업을 다시 시작함
- onPause() : 앱이 포커스를 잃었을 때 호출됨
- onStop() : 앱이 더 이상 화면에 표시되지 않음
- => 액티비티가 stopped되었지만 Activity object가 아직 memory, background에 있음
- Activity는 destroyed 되지 않음!! 사용자가 앱으로 돌아올 수 있으므로 Android는 사용자의 작업 리소스를 항상 유지함

- 액티비티가 foreground로 돌아오면, onCreate() 가 다시 호출되진 않음
- 액티비티 오브젝트가 파기되지 않았으므로 다시 생성할 필요가 없기 때문!
- onCreate() 대신 onRestart() 메소드가 호출됨
- 그리고 이후에 onStart, onResume이 호출되는 거!
- Home 버튼을 누르면 onPause, onStop 이 호출되면서 앱이 백그라운드로 이동
- 최근 화면 버튼을 이용해 다시 돌아오면 onRestart, onStart, onResume 호출
- onStart와 onStop은 사용자가 액티비티를 오갈 때 여러 번 호출된다는 것
- 앱이 백그라운드로 이동할 때 이를 중지하거나 포그라운드로 돌아갈 때 다시 시작하도록 이러한 메소드 재정의해야 함
- onResume은 액티비티에 포커스가 들어올 때 호출 됨
- onPause는 포커스가 흐트러졌을 때 호출 됨
Fragment's Lifecycle
- fragment의 생명주기는 Activity의 생명주기와 유사하며 몇 가지 고유 메소드도 있음

- onAttach() : fragment가 owner activity와 관련지어지면 호출됨.
- onCreate() : activity를 위한 onCreate와 마찬가지로, fragment가 호출되어 초기 fragment 생성(layout 제외)을 위해 호출됨
- onCreateView() method : fragment의 layout을 inflate하고 data binding이 발생함
- onViewCreated() : onCreateView() 가 반환된 직후에, 하지만 any saved state가 view에 restored되기 전에 호출됨
- onStart() : fragment가 표시되었을 때 호출됨. activity와 동일
- onResume() : fragment가 유저의 focus를 얻었을 때에만 호출됨. activity와 동일
- onPause() : fragment가 유저의 focus를 잃었을 때 호출됨. 액티비티와 동일
- onStop() : fragment가 화면에 더 이상 표시되지 않을 때 호출됨. 액티비티와 동일
- onDestroyView() : fragment의 뷰가 더 이상 필요 없게 되면, 그 뷰에 붙은 리소스를 정리하기 위해 호출됨
- Timber
- Android의 일반적인 로깅 라이브러리
- 내장 안드로이드에 비해 몇 가지 이점이 있음
- 클래스 이름을 기반으로 로그 태그 생성
- 안드로이드 앱의 릴리스 버전에 로극 표시되지 않도록 도와줌
- crash-report library와 통합할 수 있음
- 우선 Gradle에 Timber에 대한 implementation 추가해야 함
- GitHub의 Timber프로젝트 방문해서 Download 아래의 코드 복사 및 붙여넣기
implementation 'com.jakewharton.timber:timber:4.7.1'
- 모듈버전 그래들을 열고 종속성도 추가
dependencies {
...
implementation 'com.jakewharton.timber:timber:4.7.1'
}
- Applicatio nclass를 만들고 Timber 초기화
- Application 클래스는 전체 앱의 global application state를 포함하는 기본 클래스
- 운영체제가 앱고 ㅏ상호작용하기 위해 사용하는 주요 객체
- Application에 대한 기본값이 있기 때문에, 유저가 따로 특정해주지 않아도 앱을 위해 개체를 만들 수 있음
- Timber는 Application 클래스를 사용함 : 전체 앱이 이 로깅 라이브러리를 사용하기 때문에, 다른 모든 것을 설정하기 전에 라이브러리를 한 번 초기화 해야 함
- app>java>페키지 이름 을 우클릭하여 New > Kotlin file/class 선택
- 클래스 이름을 Clicker Application으로 지정하고 Kind를 class로 설정 후 확인 클릭
package com.example.android.dessertclicker
class ClickerApplication {
}
- 클래스 정의를 Application()의 하위클래스로 변경
class ClickerApplication : Application() {
- onCreate()를 덮어쓰고 그 안에서 Timber library 초기화
override fun onCreate() {
super.onCreate()
Timber.plant(Timber.DebugTree())
}
- 이 코드 행에 의해, 내 앱을 위한 timber 라이브러리를 다른 activity에서도 사용할 수 있음
- 그치만 우선 매니페스트 안에 application 요소에 name으로 방금 만든 클래스 이름 넣어줘야 됨
<application
android:name=".ClickerApplication"
...
- Timber 로그문 추가
override fun onCreate() {
super.onCreate()
Timber.i("onCreate called")
}
override fun onStart() {
super.onStart()
Timber.i("onStart Called")
}
override fun onResume() {
super.onResume()
Timber.i("onResume Called")
}
override fun onPause() {
super.onPause()
Timber.i("onPause Called")
}
override fun onStop() {
super.onStop()
Timber.i("onStop Called")
}
override fun onDestroy() {
super.onDestroy()
Timber.i("onDestroy Called")
}
override fun onRestart() {
super.onRestart()
Timber.i("onRestart Called")
}
'Android > Android Kotlin 기초 실습 정리' 카테고리의 다른 글
ViewModel : ViewModelFactory (0) | 2022.10.26 |
---|---|
LifecycleObserver, onSaveInstanceState() (0) | 2022.10.26 |
Safe Args : 프래그먼트 간 데이터 전달, intent로 외부 앱 공유 (0) | 2022.10.26 |
Navigation : Navigation components, drawer 등 (0) | 2022.10.26 |
Fragment : fragment 생성 및 layout에 fragment 추가 (0) | 2022.10.25 |
Comments