Android

Android 02. 액티비티(Activity)란?

shin96bc 2022. 5. 19. 14:17

(1) Activity(작업)

     1) Android UI 구성을 위한 가장 기본적인 요소

     2) Application 실행 시 반드시 하나 이상 필요

     3) 자체적인 그리기 기능이 있어 실행 후 화면을 그리는 것이 아닌, View 혹은 ViewGroup

         다양한 조합을 화면에 배치하여 표시

출처: 잘 모르겠습니다. 죄송합니다 ㅠㅠ

(2) Life Cycle(실행 동작 종료)

     1) onCreate, onStart, onResume, onPause, onStop, onDestroy, onRestart 7개의 메서드 사용

 

     2) onCreate() - UI 자원 할당

          <1> Java Main 메서드와 비슷한 역할. Application 실행 시 가장 먼저 호출

          <2> View 제작, View Data Binding 진행

          <3> 이전 상태의 정보를 담은 Bundle 제공 (처음은 객체의 값 null)

 

     3) onStart () - UI 이외 자원 할당(작업 복원)

          <1> Activity가 사용자에게 보여지기 직전 호출 함수

 

     4) onResume () - 작업 처리

          <1> 사용자가 Application과 상호 작용을 할 수 있는 상태의 호출 함수

          <2> Activity가 화면에 보여지는 상태로 Focus가 잡혀있음.

 

     5) onPause () - 로직 처리(작업 저장)

          <1> Activity 전환 시 호출되는 함수. Activity 호출 전 실행되는 함수.

          <2> onPause() 매서드에서 많은 작업을 진행 시 다른 Activity 호출 시간 지연.

          <3> UI 업데이트는 계속 진행 가능(ex. 네비 지도, 미디어 플레이어 재생 표시)

          <4> Data 저장 진행(많은 Data일 경우 onStop에서 진행)

          <5> Multi Window 모드에서는 onPause 상태의 Activity도 보이는 상태일 수도 있어

                 UI 관련 리소스 해제 혹은 onStop을 사용하는 것이 좋음

          <6> 이전 Activity로 전환을 원할 시 onResume 함수 호출.

 

     6) onStop () - UI 이외 자원 해체, close 작업

          <1> Activity가 더 이상 보여지지 않아도 될 경우 호출.(100%가려질 때 호출)

 

     7) onRestart ()

          <1> onStop 이후 재 시작 시 호출되는 매서드

          <2> Activity가 중지된 시간(onStop 이후) 부터의 상태를 복원

 

     8) onDestroy ()

          <1> Activity를 종료하기 직전에 호출하는 매서드.

          <2> 완전히 Stack에서 제거되기 전, 호출되는 함수. Activity 제거 시 사용

          <3> Finish 매서드 호출 혹은 시스템 메모리 확보를 위해 호출(모든 리소스 해제)

          <4> 구성 변경(ex.기기 회전 혹은 Multi Window 모드) Activtiy를 소멸시킬 경우 사용

          <5> Activity 종료 시 반드시 호출되지는 않음.(메모리 부족으로 Andorid Activity를 종료시킬 경우

                 재 시작 시 onDestroy 호출 후 onCreate 진행 가능

 

     9) Process 종료 시 Activity 초기화 가능

          <1> ViewModel, onSavedInstanceState() 혹은 Local 저장소를 통해 UI 상태 보존.

          <2> 인스턴스 상태 시스템이 이전 상태 복원을 위해 사용하는 저장 데이터, Bundle 객체에

                 Key-Value 형태로 저장. 시스템은 기본적으로 Bundle 인스턴스 상태를 사용하여 Activity

                 각 View 객체 관련 정보 저장.

 

     10) Activity 이동(화면 전환)

          <1> Intent 객체를 전달하며 화면 전환 진행

          <2> 새로 시작된 Activity에서 결과 값 반환할 필요가 없을 경우 startActivity()

          <3> 활동 종료 시 결과 값 반환 받고자 할 경우 startActivityForResult(Intent, Int)

 


 

(3) 대표적인 Activity Class 

     1) Activity Class( android.app.Activity )

          <1> 해당 안드로이드 버전의 기본 라이브러리 Activity Class 이며, 모든 다른 Activity Class는

                 이 Class 의 subClass가 된다.

     

     2) FragmentActivity Class( android.support.v4.app.FragmentActivity )

          <1> 과거 버전과의 호환성을 유지하면서 Fragment를 사용할 때 필요한 Activity Class 이다. 

 

     3) AppCompatActivity Class( android.app.support.v7.app.AppCompatActivity )

          <1> 과거 Android 버전과의 호환성을 유지하면서 새로운 버전의 기능도 사용할 수 있도록 만든

                 Activity Class 이다.

          <2> 이 Class는 Android 6.0(마시멜로)의 새로운 기능( Material Design 관련 기능 )도 많은 부분

                 구현하고 있다.

          <3> 이런 이유로 Android Studio 1.5 버전부터는 프로젝트 생성 시에 Activity를

                 AppCompatActivity Class의 subClass로 생성해준다.

 

     4) AppWidgetProvider Class

          <1> 추후 추가 예정 입니다.

 

(4) 동적 상태와 영속적 상태

     1) Activity 생명주기 관리 목적

          <1> Activity 생명주기를 관리하는 주된 목적은 적시에 Activity 상태를 저장하거나 복원하기 위함이다.

          <2> 상태( state )는 Activity가 현재 보존하고 있는 데이터와 현재 보이는 사용자 인터페이스 데이터

                 (일반적으로 핸드폰이나 대블릿 등의 화면에 나타난 뷰 객체의 데이터)를 의미한다.

 

     2) 동적 상태( Dynamic state )

          <1> 화면에 보이는 사용자 인터페이스를 동적 상태라고 한다.

                 (사용자 인터페이스 상태 또는 인스턴스 상태라고도 한다.)

          <2> 애플리케이션이 실행되는 동안만 보존되기 때문이다.

          <3> 예를 들어 화면의 텍스트 필드에 입력된 텍스트는 아직 애플리케이션의 영속적 상태 데이터로

                 확정되지 않은 것이다.

          <4> 이외에도 파일이나 데이터베이스 등에는 저장하지 않지만 Activity 내부에서 보존해야하는 

                 변수들이 필요할 수 있다. 이런 변수 데이터까지를 포함하는 것이 동적 상태 이다.

          <5> 동적 상태는 약간 복잡한 이유 때문에 데이터가 저장되고 복원된다.

          <6> 예를 들어 하나의 텍스트 필드와 몇개의 라디오 버튼( Radio Button )을 갖는 A라고 하는

                 Activity가 있을 때, 애플리케이션을 사용하는 동안 사용자는 텍스트 필드에 텍스트를 입력하고,

                 라디오 버튼을 선택한다.( Radio Button이란 여러개의 선택지 중 하나만 선택하게 끔 

                 구성되어 있는 버튼이다.) 

 

                 이때 변경 사항을 저장하기 전 사용자가 다른 Activity로 전환한다면, Activity A는 

                 Activity 스택으로 들어가고 Background 상태가 된다.

                 이후 장치의 메모리가 부족해져 Runtime 시스템이 부족한 리소스를 보충하기 위해

                 Activity A를 종결시킨다.(Kill)

 

                 그러나 사용자는 Activity A가 그냥 Background에 있다가 언제든지 Foreground로 올 준비가

                 되어 있다고 생각한다. 즉, Activity A가 Foreground로 돌아오면 자신이 입력했던 텍스트와

                 Radio Button들이 남아 있으리라 생각한다.

 

                 그러나 위의 경우 Activity A의 새로운 인스턴스가 생성되므로, 만약 동적 상태 데이터가 저장되어

                 복원되지 않았다면 사용자가 이전에 입력한 데이터는 유실된다.

                 또한 Android 장치의 구성이 변경되는 경우에도 항상 그 Activity의 인스턴스를 새로 생성한다는 

                 것에 유의하는 것이 좋다. 이는 변경된 상황에 맞게 Activity를 다시 구성해야하기 때문이다.

 

                 예를 들어, 장치를 가로 또는 세로로 전환할 때 그때마다 장치의 구성이 변경되므로 현재 화면에

                 있는 Activity의 인스턴스를 소멸시키고 새로운 인스턴스를 생성한다. 그러므로 동적 상태를 

                 저장하는 것의 주 목적은 Foreground와 Background Activity들 간의 매끄러운 전환을 

                 제공하기 위함이다.

 

     3) 영속적 상태( Persistent state )

          <1> Activity는 데이터베이스, 콘텐트 제공자, 파일 등에 저장될 필요가 있는 메모리의 데이터를 

                 유지할 수 있다. 이러한 상태정보를 영속적 상태라고 한다.

          <2> 영속적 상태를 저장하는 목적은 데이터의 유실을 막기 위함이다.

          <3> 즉, Activity가 Background 상태로 있을 때는 Runtime 시스템이 그 Activity를 종료시키면서

                 Activity의 데이터가 없어질 수 있다.

                 (Activity의 사용자 인터페이스가 현재 화면에 보이면서 사용자와 데이터를 입출력할 수 

                   있을 때는 포그라운드( Foreground ) 상태라고 한다.)

 

(5) Activity 생애

출처:&nbsp;https://mattlee.tistory.com/73

     1) 전체 생애( Entire Lifetime )

          <1> 액티비티가 생성될 때 최초 호출되는 onCreate() 메서드 호출과 종결되기 전에 호출되는 

                 onDestroy() 호출 사이에 액티비티에서 발생하는 모든 것을 나타내는 데 '전체 생애'라는

                 용어가 사용된다.

     2) 가시적 생애( Visible Lifetime )

          <1> 호출 사이의 액티비티 실행 시기다. 이 시기 동안 액티비티는 자신을 사용자에게 화면으로

                 보여줄 수 있다.

 

     3) 포그라운드 생애( Foreground Lifetime )

          <1> onResume( )메서드 호출과 onPause( )호출 사이의 액티비티 실행 시기를 의미한다.

 

(6) Activity 설계

     1) 하나의 애플리케이션에서 모든 화면 하나당 하나의 Activity로 관리를 하게 되면 apk 크기도 커지고 화면

         이동시에 소요되는 시간도 더 오래 걸릴 것입니다.

 

     2) 그러므로 너무 불필요하게 많이 만들지 않는 것을 권장하며, UI Action이 많으면 Activity 사용을 고려하고

         그게 아니라면 Fragment 나 popup으로 대체하면 좋습니다.

 

(7) 생명주기 메소드 호출 순서

     1) 시작할 때: onCreate() -> onStart() -> onResume()

출처: shin96bc

 

     2) 화면 회전할 때: onPause() -> onStop() -> onDestroy() -> onCreate() -> onStart() -> onResume()

출처: shin96bc

 

     3) 홈 버튼 클릭 시: onPause() -> onStop()

출처: shin96bc

 

     4) 홈 이동 후 다시 돌아올 때: onRestart() -> onStart() -> onResume() 

출처: shin96bc
시작부터 홈버튼 눌러서 홈 이동 후 다시 돌아오기까지 (출처: shin96bc)

 

     5) 백 버튼 클릭하여 Activity 종료 시: onPause -> onStop() -> onDestroy() 

출처: shin96bc
출처:&nbsp;https://bangu4.tistory.com/112

 

(8) Activity 전환(이동) 시 생명주기 메소드 호출

     1) Activity Main 은 onPause() 메소드를 실행합니다. (Activity A가 Background로 이동)

 

     2) Activity B 가 onCreate() -> onStart() -> onResume() 메소드를 실행하여 Foreground 상태가 됩니다.

 

     3) Activity B 가 onResume() 까지 호출된 이후에는 Foreground상태가 되고 전체화면을 가득 채우기 때문에

         Activity A 가 onStop() 메소드를 호출하게 됩니다.

 

출처: shin96bc

     4) 생명주기 메소드 호출 순서가 크게 중요하지 않다고 생각할 수 있지만, 만약 두 Activity 사이에서

         공통적으로 사용되는 Class 나 DB 가 있으면 문제가 될 수 있습니다. Activity A 가 onPause() 가 아닌

         onStop()에서 Class 나 DB를 저장할 시 Activity B 에서는 저장되지 않은 상태에서 데이터를 가져오게

         되고 그 이후에 저장되기 때문에 다른 값들을 사용하게 됩니다. 따라서 Activity 전환 시에 생명주기를

         잘 알고 사용하도록 해야합니다.

activity 왔다 갔다 해본 결과&nbsp; (출처: shin96bc)

 

(9) 생명주기 메소드 사용시 주의사항

     1) 리소스 생성/제거는 대칭으로 실행

          <1> onCeate() 에서 리소스를 생성했으면 onDestroy() 에 해제를 하고 onResume() 에 생성하면 

                 onPause() 에 제거를 해서 대칭적으로 코드를 작성해야 합니다.

 

          <2> DB를 onCreate() 에서 열었고 onPause() 가 되면 닫는다고 가정했을 때 재시작이 되면

                 닫힌 DB를 열기 때문에 문제가 발생할 수 있습니다. 즉, onCreate() 에서 열었다면 

                 onDestroy() 에 닫도록 해야합니다.

 

     2) finish() 메서드 호출 후 return 필수

          <1> finish() 메서드로 Activity 종료 시에 finish() 메서드는 시스템에 Activity를 종료하라는 메시지를 

                 보낼 뿐 return을 하는게 아닙니다.

 

          <2> finish() 메서드 이후에도 로직이 있다면, 해당 로직이 수행될 수있으며 정상적인 결과를 얻지 

                 못하거나, 오류가 발생하게 될 수 있습니다. 

 

          <3> 따라서 finish() 메서드를 호출했다면 return을 필수로 추가하여 이후 로직이 실행되지 않도록

                 해야합니다.

 

(10) Activity 와 Service

     1) Activity 에서 Service 로 데이터 전달

          <1> Activity 에서 Service 로 데이터를 전달하고 싶을 때는 Activity 에서 startService() 메서드를

                 호출해서 Intent 객체를 넘겨준다.

출처: https://pangtrue.tistory.com/135

          <2> Service 에서는 onStartCommand() 메서드로 Intent 객체를 받는다.

                 (onCreate() 는 처음 만들어질때 딱 한번만 호출된다.)

출처:&nbsp;https://pangtrue.tistory.com/135

 

     2) Service 에서 Activity 로 데이터 전달

          <1> Service 에서 Activity 로 데이터를 전달하고 싶을 때는 Service 에서 startActivity() 메서드를 

                 호출하면서 Intent 객체를 전달하면 Activity 에서는 그 안에 들어 있는 부가데이터를 받을 수

                 있습니다.

출처:&nbsp;https://bite-sized-learning.tistory.com/139

          <2> 먼저 Service 라고 하는 것은 화면이 존재하지 않습니다. 그래서 이렇게 화면이 없는 곳

                 ( Service 객체) 에서 화면쪽으로(Activity) 화면을 띄워달라고 요청을 하면 문제가 발생합니다.

                 왜냐하면 화면이라는 것은 Task라는 것으로 묶여 있습니다. 이 Task 는 내가 만든 화면도 있고,

                 다른 사람이 만든 앱의 화면도 있습니다. 그 애플리케이션 각각의 화면

                 (기본 브라우저, 전화걸기 화면 등) 끼리는 필요할 때 Intent 로 화면을 띄워줄 수 있는데,

                 그런 경우에 각각의 화면이 연속적으로 띄워질 수 있도록 만들어 놓은 것이 Task 입니다.

                 

                 그런데 화면이 없는 곳에서 화면을 띄우려고 한다면 Task 라는 정보가 없어서 화면을 띄우는데

                 문제가 생길 수 있습니다. 그래서 항상 화면이 없는 Service 에서 화면이 있는 Activity 를

                 호출할 때는 addFlags() 메소드를 사용해서 옵션을 설정해줘야합니다.

 

          <3> 먼저 화면이 없는 Service 에서 화면이 있는 Activity 를 띄우려면 새로운 태스크를 만들어야

                 합니다. 그래서 addFlags()에 새로운 태스크( Tesk )를 생성하도록

                 FLAG_ACTIVITY_NEW_TASK 라는 FLAG INTENT를 추가해야 합니다.

 

          <4> 두번째로는 이미 Activity 객체가 메모리에 만들어져 있는 경우에는 재사용하도록                           

                 FLAG_ACTIVITY_SINGLE_TOP 이라는 FLAG INTENT 를 추가해야 합니다.

 

          <5> 마지막으로 만약 그 위에 다른 화면이 있으면 그 화면을 제거해주는

                 FLAG_ACTIVITY_CLEAR_TOP 이라는 FLAG INTENT 도 추가해야합니다.

 

          <6> Activity 에서 Service 의 데이터를 받을 때 넘겨 받을 때는 만약 호출된 Activity 가 이미 메모리에

                 만들어져 있다면 onCreate() 메서드는 호출되지 않고, onNewIntent() 메서드가 호출됩니다.

                 그리고 Intent 는 메서드의 파라미터로 전달됩니다.

출처:&nbsp;https://bite-sized-learning.tistory.com/139

     3) Service 를 사용하는 이유

          <1> 요즘 앱들은 웹서버나 서버 쪽하고 데이터를 주고 받는 경우가 많습니다.

                 데이터를 주고 받을 때, 그 데이터를 주고 받는 작업 자체는 화면이 필요없습니다.

          <2> 그리고 서버에서 데이터를 실시간으로 받기 위해서는 기본적으로 항상 데이터를 받기 위해

                 대기 상태에 있어야지 서버쪽에서 보내온 데이터를 받아서 처리할 수 있을 것입니다.

          <3> 이렇게 화면이 필요없고, 항상 Background 에서 대기 상태로 존재해야하는 작업에 Service 를

                 사용합니다.

          <4> 예를 들어 카톡이나 라인 같은 채팅앱 같은 경우에 항상 새로운 메시지를 실시간으로 받아와야

                 하기때문에 Service 가 많이 사용됩니다.

                (그 외에도 Background 에서 계속 실행되어야하는 음악재생 기능 같은 것들에도 많이 사용됩니다.)

 

 

참고자료:

 https://mattlee.tistory.com/73

 

 https://bite-sized-learning.tistory.com/139

 

 https://pangtrue.tistory.com/135

 

 https://bangu4.tistory.com/112