액티비티란?
사용자에게 UI가 있는 화면을 제공하는 앱 컴포넌트입니다.
안드로이드는 반드시 하나 이상의 액티비티를 포함하고 있고 , 액티비티는 생명주기 관련 메서드를 재정의하여 기능을 구현할 수 있습니다.
액티비티는 생성과 소멸까지의 생명주기를 가지고 있습니다.
액티비티를 잘 사용하기 위해서는 생명주기에 대해 잘 아시는게 중요합니다.!
생명주기에는 onCreate(), onStart() ,onRestart() , onResume(), onPause() , onStop() , onDestroy()가 있습니다.
액티비티가 새로운 상태에 들어가면 각 콜백 메서드를 호출합니다
생명주기를 더 잘 이해하시려면 이 자료를 보시기 추천합니다.!
이미지 출처 : developer.android.com/guide/components/activities/activity-lifecycle?hl=ko
- onCreate()
액티비티를 실행할 때 최초로 실행이 되며 , 필수적으로 구현하셔야 합니다.
onCreate()에서는 액티비티가 실행될 동안 한번만 발생해야 하는 기본 애플리케이션 로직을 작성해야 합니다.
그래서 뷰의 초기화 , 데이터들의 초기화가 이루어집니다.
onCreate()가 호출이 되면 연달아 onStart()와 onResume() 메서드가 호출이 됩니다.
- onStart()
액티비티가 사용자에게 보이기 직전에 호출이 됩니다.
- onRestart()
onStart()와의 차이점은 onStop()가 되었다가 다시 돌아왓을 때만 실행된다는 점입니다.
- onResume()
이 상태에 들어가게 되면 앱이 사용자와 상호작용합니다.
어떤 이벤트가 발생하여 앱에서 포커스가 떠날때까지는 앱이 이상태에서 머무르게 됩니다.
방해되는 이벤트가 발생이 되면 활동은 일시 중지가 되고 onPause() 콜백을 호출하게 됩니다.
- onPause()
액티비티가 팝업이 띄어지거나 , 포커스를 잃어버리게 되면 onPause()가 호출됩니다.
- onStop()
액티비티가 완전히 보이지 않으면 이 상태에 들어가게 됩니다.
- onDestroy()
액티비티가 완전히 종료되었을 때 onDestroy()가 호출됩니다.
각각의 생명주기를 잘고려해서 코드를 작성해야 합니다.
언제 호출이 되는지 확인해보기 위해 각 생명주기에 호출되는 메서드를 작성해보았습니다.
앱이 실행될 경우와 앱이 다른 액티비티로 이동했을 경우, 다른액티비티로 이동했다가 다시 그전 액티비티로 이동하는 경우로 나누어 확인해보겠습니다.
확인을 더 쉽게 해 보기 위해 각 메서드에 로그를 찍어보았습니다.
더 빠르게 작성할 수 있는 Tip) 이렇게 스틱 코드를 이용하시면 메서드들을 하나씩 작성하지않더라도 한 번에 작성하실 수 있습니다.
(하나씩 작성하기 귀찮아서 스틱코드를 이용해서 한번에 생명주기를 작성하고는 합니다.)
스틱코드 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 - 생명주기 로그 찍기
'안드로이드 자바' 카테고리의 다른 글
[Java][Android] 바텀 네비게이션 with 프래그먼트 만들기 (6) | 2021.02.16 |
---|---|
[Java][Android] 실시간 이메일 정규식 체크 기능을 만들어 보자 (0) | 2021.02.15 |
[Java][Android] 내 입맛대로 다이얼로그 커스텀하기 (0) | 2021.02.12 |
[Java][Android] 안드로이드 - 토스트(Toast) (0) | 2021.02.11 |
[Java][Android] Service로 음악 재생하는 앱 빠르게 만들기 (0) | 2021.02.10 |