안드로이드 App Components - Activity

Min Young Kim·2022년 10월 5일
0

Concepts From.
https://developer.android.com/guide/components/activities/intro-activities

액티비티(Activity)

  • 한 앱이 다른 앱을 호출할 때 호출 앱은 다른 앱을 전체적으로 호출하는 것이 아니라 다른 앱의 활동을 호출함
  • 사용자가 애플리케이션과 상호작용하는 단일화면
  • 사용자와 상호작용을 담당하는 인터페이스
  • 생명주기(Life Cycle) 관련 메서드들을 재정의하여 원하는 기능들을 구현할 수 있음
  • 인텐트(Intent)를 통해 다른 애플리케이션의 액티비티를 호출할 수 있음
  • 2개 이상의 액티비티를 동시에 Display 할 수 없음
  • 1개 이상의 View 또는 ViewGroup 을 포함함
  • 애플리케이션에는 반드시 하나 이상의 액티비티가 있어야 함
  • 액티비티 내에 프래그먼트(Fragment)를 추가하여 화면을 분할시킬 수 있음
  • 활동을 선언하려면 manifest 에 요소를 추가해야 함

생명주기 (Life Cycle)

액티비티 생명주기

생명주기를 잘 구현하면 예방할 수 있는 문제

  • 사용자가 앱을 사용하는 도중에 전화가 걸려오거나 다른 앱으로 전환할 때 비정상 종료되는 문제
  • 사용자가 앱을 활발하게 사용하지 않는 경우 귀중한 시스템 리소스가 소비되는 문제
  • 사용자가 앱에서 나갔다가 나중에 돌아왔을 때 사용자의 진행 상태가 저장되지 않는 문제
  • 화면이 가로 방향과 세로 방향간에 회전할 경우, 비정상 종료되거나 사용자의 진행 상태가 저장되지 않는 문제

생명주기 함수

  • onCreate()

  • 액티비티에서 한번 발생하는 기본적인 어플리케이션 구동 로직이 일어남

  • 데이터를 리스트에 묶거나, 액티비티를 뷰모델에 연결시키거나, 클래스의 변수를 인스턴스화 함(클래스로부터 객체를 생성)

  • onStart()

  • 사용자에게 액티비티가 보여지고, 상호작용이 가능하도록 만들어줌

  • UI를 가지고 있는 코드를 시작하도록 만들어줌

  • onResume() 으로 곧바로 넘어감

  • onResume()

  • 포커스가 다른 앱으로 넘어가기 전까지 이 단계에 머물러 있음 (전화, 다른 앱 실행, 화면 끄기)

  • 포그라운드에서 사용자에게 보이는 동안 실행해야 하는 모든 기능을 활성화함

  • 멀티윈도우 환경에서 구동되도록 하고 싶다면 onStart 이벤트에 연결시키고, 메인으로 되어있을때 구동되도록 하고 싶으면 onResume 이벤트에 연결시켜야 함

  • onStart 이벤트에서 사용된 리소스는 onStop 이벤트에서 해제되고, onResume 이벤트에서 사용된 리소스는 onPause 이벤트에서 해제된다.

  • onPause()

  • 사용자의 포커싱이 옮겨진 경우 , 멀티 윈도우로 실행된 경우, 다이얼로그 창이 위에 뜬 경우 onPause 상태로 들어감

  • 잠깐 실행되는 메서드로 어플리케이션 데이터 저장이나 네트워크 호출 등의 작업을 이곳에서 하면 안된다.

  • 시스템 리소스를 해제할 때도 사용 가능. GPS 같은 센서나, 사용자가 더 이상 필요로 하지 않지만 배터리에 영향을 줄 수 있는 액티비티 등

  • 하지만 멀티윈도우 모드를 고려하여 onStop 상태에서 리소스를 해제하는것을 고려해야한다.

  • onStop()

  • 액티비티가 더 이상 사용자에게 보이지 않을때, onStop 상태로 들어온다. (새로운 액티비티가 화면을 가득 채웠을 경우)

  • 앱이 사용자에게 보이지 않을때 어떤 리소스를 해제하거나 조정해줄지 결정해야함

  • CPU의 사용량을 조절하기 위해서도 onStop 을 활용해야한다 (더 이상 정보를 저장할 공간이 없을때)

  • 액티비티가 onStop 상태에 들어갔을때, activity object를 메모리에 저장하여 다시 실행했을 때에도 정보가 유지되게 된다.

  • onDestroy()

  • 액티비티가 완전히 종료되거나, 화면전환, 멀티윈도우 모드 같이 시스템이 잠시 꺼졌다가 다시 켜지는 경우

  • 액티비티에 destroy가 일어나는 이유를 명시하는 것 보다 viewModel 오브젝트를 사용하는 것이 더 좋다.

  • 화면 회전과 같이 액티비티가 destroy 후 다시 재생성 될때는 viewModel은 그대로 보존되어 액티비티에서 다음 액티비티로 정보를 넘겨주면 되고, 액티비티가 재생성 되지 않고 완전히 제거 될때는 viewModel 에서 onCleared() 함수를 사용하여 데이터를 다 지워주면 된다.

  • 두가지 경우를 isFinishing() 함수를 통해서 구별할 수 있다.

생명주기의 3가지 종류

  • 활성 상태

  • 액티비티가 화면을 점유하여 출력되고 있으며 사용자 이벤트 처리가 정상으로 처리되는 상태

  • onCreate() → onStart() → onResume() 함수가 호출되면서 활성 상태로 들어감

  • 일시정지 상태

  • 현재 액티비티가 일시적으로 사용이 불가능한 상태

  • onPause() 함수가 자동으로 호출됨

  • 비활성 상태

  • 현재 액티비티가 다른 액티비티로 인해 화면이 완벽하게 가려진 상태

  • onPause() → onStop() 함수까지 호출됨

  • 화면을 가렸던 액티비티가 다시 호출되면 onRestart() → onStart() → onResume() 함수가 차례로 호출됨

  • 액티비티 상태 저장

  • 액티비티에서 사용하던 데이터를 액티비티가 종료된 뒤 다시 사용할때 유지시켜야 할 경우가 있음 (ex. 화면 회전)

  • 화면이 회전될 때, onPause() → onStop() → onDestroy() 함수까지 호출되어서 종료된 뒤, 다시 onCreate() → onStart() → onResume() 함수 순으로 호출됨. 이때 그 전에 있던 데이터가 모두 유실된다.

  • 그렇기 때문에 데이터를 복원하여 사용하기 위한 생명주기 함수가 있음.

  • 액티비티가 종료되는 상황에 대비하여 데이터를 저장할때 onSaveInstanceState() 를 사용

  • 데이터는 매개변수로 전달되는 Bundle 을 사용, Map 객체로써 데이터를 key-value 형식으로 담을 수 있음

  • 액티비티가 다시 시작되면, onRestoreInstanceState() 함수를 사용하여 저장된 데이터를 가져옴

  • API Lv21 버전부터 매개변수가 2개인 saveinstance, restoreinstance 함수가 추가됨

  • 매개변수가 2개인 함수는 onPause() 함수 호출 후 무조건 적으로 호출되지는 않으며, Bundle에 저장된 데이터가 없으면 호출되지 않음

startActivity() & startActivityForResult()

startActivity()

  • 새로 시작된 활동이 결과를 반환할 필요가 없을 경우
  • 실행하고자 하는 동작을 설명하는 인텐트를 생성하면 시스템이 적절한 활동을 다른 애플리케이션에서 시작함

startActivityForResult()

  • 활동이 종료될 때 결과를 반환받고자 하는 경우

태스크(스택) 관리

  • 스택 형식으로 액티비티가 쌓임 ( LIFO 후입선출)
  • 태스크는 앱 실행을 위한 정보 저장공간, 액티비티의 각종 정보(시스템 내부 정보)를 저장하기 위한 공간
  • 안드로이드 시스템에서는 태스크 정보를 이용해 앱을 어떻게 수행할지 결정
  • 프로세스는 앱의 물리적 실행 단위, 태스크는 앱의 논리적 실행 단위
  • 사용자 관점을 고려한 프로그램의 실행단위

태스크 관리를 제어하는 법

  • 기본적으로 시스템에서 제어를 해주지만, 개발자가 직접 제어해야 할 경우가 있음 (두가지 방법)

1. AndroidManifest.xml 파일의 설정에 액티비티가 실행될때 태스크 목록에 어떻게 올라가야 하는지 명시하는 방법

  • launchMode 로 액티비티의 실행과 태스크에 적용되는 것을 관리

<activity android : name = "액티비티 이름", android : launchMode = "속성값">

  • launchMode 의 속성값
  1. standard (기본값)
  • 인텐트가 발생하면 매번 액티비티를 생성하고 태스크 목록에 반복해서 올린다.
  1. singleTop
  • 실행하려는 액티비티가 태스크의 최상단에 있으면 다시 생성하지 않는다.

  • 객체 생성 없이 화면에 보여주는 내용을 전환하고자 할때, onNewIntent() 함수를 사용한다.

  1. singleTask
  • 실행되는 시점에 새로운 태스크 목록을 만들어 그곳에 액티비티 정보를 저장한다.

  • 인텐트에 의해 각기 다른 앱이 실행될때도 새로운 태스크가 생성된다.

  1. singleInstance
  • 액티비티별로 하나의 태스크를 차지하게 되어, 다른 액티비티가 실행된다면 각자 다른 태스크에 쌓이게 된다.

2. 액티비티를 실행하는 인텐트에 플래그(Flag)를 이용하여 태스크 목록에 어떻게 올라가야 하는지 명시하는 방법

  • setFlags() 함수를 이용, 매개변수는 상수 문자열을 주어 지정
  1. FLAG_ACTIVITY_NEW_DOCUMENT
  • 태스크 목록을 리셋하고, 이전 액티비티 정보를 삭제
  1. FLAG_ACTIVITY_CLEAR_TOP
  • 실행되는 액티비티의 상단 태스크 정보 삭제 (바로 이전 액티비티 삭제)

3-1. FLAG_ACTIVITY_NEW_TASK

3-2. FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

  • 새로운 태스크 목록을 만들어 액티비티 정보 저장

  • new_task 와 함께 쓰이며 최근 실행한 앱 목록에 새로운 태스크 앱 정보가 나오지 않음

  1. FLAG_ACTIVITY_FORWARD_RESULT
  • 인텐트 실행 결과를 이전 액티비티에 전달

  • 데이터 획득은 onActivityResult() 함수를 사용

  1. FLAG_ACTIVITY_NO_HISTORY
  • 액티비티를 실행하면서 태스크 목록에 저장되지 않게 설정
  1. FLAG_ACTIVITY_REORDER_TO_FRONT
  • 실행되는 액티비티를 태스크 목록에서 최상위로 올리기 위한 설정
  1. FLAG_ACTIVITY_SINGLE_TOP
  • 액티비티가 태스크 목록에서 최상위에 있을 때 생성하지 않는 설정

액티비티가 출력되는 창(window)의 설정

1. 키보드 제어

  • showSoftInput(View view, int flags) : 키보드 보임

  • hideSoftInputFromWindow(IBinder windowToken, int flags) : 키보드 숨김

  • 뷰에 포커스가 없는 경우 키보드가 나타나지 않으므로 requestFocus() 함수를 사용하여 포커스를 요청해야함

  • toggleSoftInput(int showFlags, int hideFlags) : 키보드가 보인다면 숨기고, 숨겨져 있다면 보여주기

  • 키보드를 올리면서 액티비티가 차지하고 있던 화면의 영역에 변화를 줄 수 있음.

2. 다중 창 지원

  • 안드로이드 스크린을 불할하여 한 화면에 두 앱을 동시에 띄울 수 있는 기능

  • 작업이 멈추는걸 onPause() 가 아닌 onStop() 함수에서 작업을 해주어야함

  • 다중 창을 지원하고 싶지 않다면 액티비티의 resizeableActivity 속성값을 false 로 지정하면 된다.

  • isInMultiWindowMode() : 액티비티가 다중 창 모드에 있는지 확인

  • onMultiWindowModeChanged() : 액티비티가 다중 창 모드로 들어가거나 나올 때 콜백 함수

3. PIP (Picture In Picture)

  • 동영상을 전체화면으로 보여주다가 바탕화면등으로 빠져나가면 한 귀퉁이에 줄여서 보여주는 기법

  • isInPictureInPictureMode() : 액티비티가 PIP 모드인지 확인

  • onPictureInPictureModeChanged() : 액티비티가 PIP모드로 전환되거나 PIP 모드에서 해제될때 호출

  • enterPictureInPictureMode() : 액티비티를 PIP 모드로 전환

4. 화면 회전

  • screenOrientation 속성으로 액티비티의 방향을 고정

  • configChanges 속성으로 화면이 회전되는 순간을 감지

5. 태스크 제어

  • alwaysRetainTaskState : true로 설정시 오랜 시간이 지나도 태스크 내의 모든 액티비티 유지

  • clearTaskOnLaunch : true면 이 앱이 다시 활성 상태가 될 때 루트 액티비티를 제외한 나머지 액티비티 제거

  • finishOnTaskLaunch : true 면 앱이 다시 활성 상태가 될 때 이 속성이 설정된 액티비티 제거

profile
길을 찾는 개발자

0개의 댓글