기록장
[안드로이드] Flag 플래그 이해하기 본문
Intent를 배우면서 새로운 화면을 호출하고 데이터를 넘겨주는 방법을 알았다. 그러나 새로운 액티비티를 호출하였을 때 호출한 액티비티는 어떻게 되는지 궁금할 수 있다. 결론적으로는 호출하는 것마다 스택에 쌓이게 되는데 이런 액티비티들을 조정해주는 역할을 하는 Flag(플래그)대해 알아보겠다.
액티비티는 ActivityManager라는 객체에 의해 Activity Stack 이라는 것으로 관리된다.
startActivity나 startActivityForResult를 사용하여 새로운 액티비티를 호출하게 되면 호출 전 액티비티는 스택에 들어가고 호출된 화면이 보여질 것이다.
스택 처리 과정을 설명하자면
액티비티1 -> 액티비티2 -> 액티비티3 -> 액티비티2 -> 액티비티3
이 상황에서 현재 우리가 보는 화면에는 액티비티3 이 보이고 있을 것이다. 액티비티3에서 back을 누르게 되면 액티비티2가 나오고, 또 다시 back을 하면 3이보이고 .. 이런 식이다.
결국 동일한 액티비티를 여러 번 실행하는 것은 비효율적(자원 사용에 있어서나 이러나 저러나..)이다.
그래서 이런 문제를 다룰 수 있는 대표적인 플래그 3가지를 알아보도록 하겠다.
FLAG_ACTIVITY_SINGLE_TOP
FLAG_ACTIVITY_NO_HISTORY
FLAG_ACTIVITY_CLEAR_TOP
1. FLAG_ACTIVITY_SINGLE_TOP
이 플래그를 사용하게 되면 같은 액티비티에서 같은 액티비티를 호출하게 되면 스택에 쌓이지 않고 원래 보여지던 화면(호출 전 액티비티)이 보여지게 된다. 그리고 이런 경우에는 onCreate()가 호출되지 않고, onNewIntent() 메소드를 정의하여 사용하여야 한다. 한마디로 재사용될 경우 onNewIntent() 메서드에 필요한 작업을 만들어야 한다는 것이다.
물론 다른 새로운 액티비티가 호출된다면 onCreate()의 getIntent() 메소드로 넘어온 데이터를 참조할 수 있다.
코드
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:gravity="center_horizontal|center_vertical"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="버튼"
android:id="@+id/button1"/>
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
Button b1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle("첫번째 액티비티");
b1 = findViewById(R.id.button1);
b1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), second.class);
startActivity(intent);
}
});
}
}
activity_second.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".second"
android:gravity="center">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="버튼"
android:id="@+id/button1" />
</LinearLayout>
second.java
public class second extends AppCompatActivity {
Button b1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
setTitle("두번째 액티비티");
b1 = findViewById(R.id.button1);
b1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), second.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
}
});
}
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Toast.makeText(getApplicationContext(), "onNewIntent 호출",Toast.LENGTH_SHORT).show();
}
}
2. FLAG_ACTIVITY_NO_HISTORY
이 플래그를 사용하면 처음 이후에 실행된 액티비티는 Activity Stack에 추가되지 않는다.
쉽게 이해를 하자면 어떤 액티비티에서 FLAG_ACTIVITY_NO_HISTORY를 포함하여 또 다른 액티비티를 호출하면 호출된 액티비티는 스택에 쌓이지 않는다고 이해하면 될 것이다.
MainAcitivity.java
public class MainActivity extends AppCompatActivity {
Button b1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle("첫번째 액티비티");
b1 = findViewById(R.id.button1);
b1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), second.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);
}
});
}
}
second.java
public class second extends AppCompatActivity {
Button b1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
setTitle("두번째 액티비티");
b1 = findViewById(R.id.button1);
b1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
}
});
}
}
위 코드를 실행하여 액티비티 상태를 메인 -> 세컨드 -> 메인 -> 세컨드 -> 메인 이런 상태를 만들고 back 키를 누르면서 본다면 이해하기 쉬울 것이라고 생각한다.
3. FLAG_ACTIVITY_CLEAR_TOP
이 플래그를 사용하면 이 액티비티 위에 있는 다른 액티비티들을 모두 종료시키게 된다.
예를 들어, 액티비티 1 -> 2 -> 3 -> 2 -> 1 -> 2 -> 3 -(플래그)-> 1 이렇게 호출된 상황에서는 1 -> 2 -> 3 -> 2 -> 1 만 남고 맨 뒤의 2와 3은 사라진다.
코드를 직접 돌려보면서 이해하는 것이 빠를 것 같다고 생각한다.
코드
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:gravity="center_horizontal|center_vertical"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="두번째로"
android:id="@+id/button1"/>
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
Button b1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle("첫번째 액티비티");
b1 = findViewById(R.id.button1);
b1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), second.class);
startActivity(intent);
}
});
}
}
activity_second.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".second"
android:gravity="center">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="세번째로"
android:id="@+id/button1" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button2"
android:text="첫번째로"/>
</LinearLayout>
second.java
public class second extends AppCompatActivity {
Button b1,b2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
setTitle("두번째 액티비티");
b1 = findViewById(R.id.button1);
b2 = findViewById(R.id.button2);
b1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), third.class);
startActivity(intent);
}
});
b2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
}
});
}
}
activity_third.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".third"
android:gravity="center">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="첫번째로"
android:id="@+id/button1"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button2"
android:text="두번째로"/>
</LinearLayout>
third.java
public class third extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_third);
setTitle("세번째 액티비티");
Button b1 = findViewById(R.id.button1);
Button b2 = findViewById(R.id.button2);
b1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
});
b2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), second.class);
startActivity(intent);
}
});
}
}
플러그에 대해 공부해보았는데 무엇을 만드는데 있어서 실질적으로 적용하려면 시간이 조금 걸릴 것 같다.
계속 공부해봐야겠다..
부족한 점, 피드백 환영합니다.
감사합니다.
참고
정재곤, 『Do it! 안드로이드 앱 프로그래밍 - 개정 6판』, 이지스퍼블리싱(주)
'안드로이드' 카테고리의 다른 글
[안드로이드] Fragment 이해하기(1) (0) | 2021.01.03 |
---|---|
[안드로이드] SharedPreferences / 데이터 저장, 복원 (0) | 2021.01.01 |
[안드로이드] 액티비티의 생명주기 (0) | 2021.01.01 |
[안드로이드] Intent / 데이터 주고 받기, 액티비티 전환 (0) | 2020.12.30 |
[안드로이드] AlertDialog 클래스 / 알림창, 대화상자 띄우기 (0) | 2020.12.29 |