본문 바로가기
안드로이드 자바

[Java][Android] 안드로이드 액티비티 생명주기

by teamnova 2021. 2. 14.
728x90
액티비티란?

사용자에게 UI가 있는 화면을 제공하는 앱 컴포넌트입니다. 

안드로이드는 반드시 하나 이상의 액티비티를 포함하고 있고 , 액티비티는 생명주기 관련 메서드를 재정의하여 기능을 구현할 수 있습니다.

 

액티비티는 생성과 소멸까지의 생명주기를 가지고 있습니다.

액티비티를 잘 사용하기 위해서는 생명주기에 대해 잘 아시는게 중요합니다.!

 

 

 

 

활동 수명 주기에 관한 이해  |  Android 개발자  |  Android Developers

활동은 사용자가 전화 걸기, 사진 찍기, 이메일 보내기 또는 지도 보기와 같은 작업을 하기 위해 상호작용할 수 있는 화면을 제공하는 애플리케이션 구성요소입니다. 각 활동에는 사용자 인터페

developer.android.com

 

생명주기에는  onCreate(), onStart() ,onRestart() , onResume(), onPause() , onStop() , onDestroy()가 있습니다.

액티비티가 새로운 상태에 들어가면 각 콜백 메서드를 호출합니다

생명주기를 더 잘 이해하시려면 이 자료를 보시기 추천합니다.!

 

액티비티 생명주기

 

이미지 출처 : developer.android.com/guide/components/activities/activity-lifecycle?hl=ko

 

활동 수명 주기에 관한 이해  |  Android 개발자  |  Android Developers

활동은 사용자가 전화 걸기, 사진 찍기, 이메일 보내기 또는 지도 보기와 같은 작업을 하기 위해 상호작용할 수 있는 화면을 제공하는 애플리케이션 구성요소입니다. 각 활동에는 사용자 인터페

developer.android.com

 

- onCreate()

액티비티를 실행할 때 최초로 실행이 되며 , 필수적으로 구현하셔야 합니다.

onCreate()에서는 액티비티가 실행될 동안 한번만 발생해야 하는 기본 애플리케이션 로직을 작성해야 합니다.

그래서 뷰의 초기화 , 데이터들의 초기화가 이루어집니다.

onCreate()가 호출이 되면 연달아 onStart()와 onResume() 메서드가 호출이 됩니다.

 

- onStart()

액티비티가 사용자에게 보이기 직전에 호출이 됩니다.

 

- onRestart()

 onStart()와의 차이점은 onStop()가 되었다가 다시 돌아왓을 때만 실행된다는 점입니다.

 

- onResume()

이 상태에 들어가게 되면 앱이 사용자와 상호작용합니다.

어떤 이벤트가 발생하여 앱에서 포커스가 떠날때까지는 앱이 이상태에서 머무르게 됩니다.

방해되는 이벤트가 발생이 되면 활동은 일시 중지가 되고 onPause() 콜백을 호출하게 됩니다.

 

- onPause()

액티비티가 팝업이 띄어지거나 , 포커스를 잃어버리게 되면 onPause()가 호출됩니다.

 

- onStop()

액티비티가 완전히 보이지 않으면 이 상태에 들어가게 됩니다.

 

- onDestroy()

액티비티가 완전히 종료되었을 때 onDestroy()가 호출됩니다.

 

각각의 생명주기를 잘고려해서 코드를 작성해야 합니다.

 

 

언제 호출이 되는지 확인해보기 위해 각 생명주기에 호출되는 메서드를 작성해보았습니다.

앱이 실행될 경우와 앱이 다른 액티비티로 이동했을 경우, 다른액티비티로 이동했다가 다시 그전 액티비티로 이동하는 경우로 나누어 확인해보겠습니다. 

확인을 더 쉽게 해 보기 위해 각 메서드에 로그를 찍어보았습니다.

 

더 빠르게 작성할 수 있는 Tip) 이렇게 스틱 코드를 이용하시면 메서드들을 하나씩 작성하지않더라도 한 번에 작성하실 수 있습니다. 

(하나씩 작성하기 귀찮아서 스틱코드를 이용해서 한번에 생명주기를 작성하고는 합니다.)

 

 

스틱코드에 저장해 놓은 생명주기 코드

 

스틱코드 stickode.com/

 

STICKODE - 스틱코드

스틱코드에서 개발에 필요한 모든 코드를 쉽게 사용하세요

stickode.com

 

1. 앱이 처음 실행될 때

각 생명주기가 호출될 때 로그를 출력하도록 작성했습니다.

 

MainActivity.java

 

package com.example.stickode;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;


public class MainActivity extends AppCompatActivity {

    private static String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.d(TAG,"onCreate");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG,"onStart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG,"onResume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG,"onPause");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.d(TAG,"onRestart");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG,"onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG,"onDestroy");
    }


}

 

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

로그는 onCreate -> onStart -> onResume순으로 찍힌 것을 확인할 수 있습니다.

앱이 처음 실행될때 생명주기

 

 

2. 다른 액티비티로 이동할 경우

각 생명주기가 호출될 때 로그를 출력하도록 작성하고 , move 버튼을 누르면 moveActivity로 이동하도록 작성했습니다.

MainActivity.java
package com.example.stickode;
import android.content.Intent;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;


public class MainActivity extends AppCompatActivity {

    private static String TAG = "MainActivity";
    Button moveBtn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        moveBtn =  findViewById(R.id.moveBtn);

        moveBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplicationContext(),MoveActivity.class);
                startActivity(intent);
            }
        });

        Log.d(TAG,"onCreate");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG,"onStart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG,"onResume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG,"onPause");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.d(TAG,"onRestart");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG,"onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG,"onDestroy");
    }


}
activity_main.xml

 

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/moveBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="MOVE"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

 

MoveActivity.java
package com.example.stickode;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class MoveActivity extends AppCompatActivity {

    private static String TAG = "MoveActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_move);
        
        Log.d(TAG,"onCreate");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG,"onStart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG,"onResume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG,"onPause");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.d(TAG,"onRestart");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG,"onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG,"onDestroy");
    }
}
activity_move.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MoveActivity">

    <TextView
        android:text="Hello"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

Move버튼을 눌렀을 때는 MainActivity onPause()가 호출되고 MoveActivity의 onCreate() -> onStart() -> onResume()이 순서로 호출된 후에 다시 MainActivity의 onStop()이 호출이 되는 것을 확인할 수 있습니다.

다른액티비티로 이동했을 때 생명주기

 

 

3. 다른 액티비티로 이동하고 다시 그 전 액티비티로 돌아올 경우

코드는 2번과 동일합니다.

다시 뒤로 가기를 할 경우 MoveActivity onPause()가 호출되고 , MainActivity에 onRestart()->onStart()->onResume()이 실행되고 난 후 MoveAcitity가 onStop()->onDestroy()가 호출되는 것을 확인할 수 있습니다.

 

다른 액티비티로 이동하고 다시 그 전 액티비티로 돌아올때 생명주기

 

로그를 직접 찍어보시면서 하시면 생명주기에 대해 더 잘 이해하실 수 있을 것 같습니다.!

 

저는 앱을 처음 실행할 때 , 다른 액티비티로 이동할 때 , 다른 액티비티에서 이동했다가 다시 전 액티비티로 돌아왔을 때 로그를 찍어봤지만

더 다양하게 홈키를 눌렀을 때 , 앱이 완전히 종료되었을 때 , 팝업창을 띄웠을 때 등 다양하게 테스트를 해보시면서 생명주기를 이해하시면 더 좋을 것 같습니다. 

 

또한 스틱 코드를 이용해서 작성하면 생명주기를 더 빠르게 작성할 수 있고 , 로그도 한번에 찍을 수 있습니다.

 

이 예제에서 사용한 스틱코드 

stickode.com/code.html?fileno=9230   - 생명주기 로그 찍기