=======================
=======================
=======================
출처: http://neoroid.tistory.com/201
예를들어 A, B, C Activity가 있다고 칩시다.
A에서 B로 갈 때 finish()를 하지 않고 갑니다.
즉,
Intent intent = new Intent(A.this, B.class); startActivity(intent); |
startActivity(intent); 만 이용해서 이동한 것이지요.
그렇게 B로 이동한 후 또 C로 이동합니다.
Intent intent = new Intent(B.this, C.class); startActivity(intent); |
이렇게 C로 이동한 후 이동 한 후 C를 종료하면서 A로 바로 이동하고 싶습니다. 그런데 A로 이동하면서 B도 끄고 싶습니다.
이런경우 보통 FLAG_ACTIVITY_CLEAR_TOP 플래그를 이용해서 이동합니다.
Intent intent = new Intent(C.this, A.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); finish(); |
하지만 Activity가 많아질 경우 FLAG_ACTIVITY_CLEAR_TOP 은 더이상 통하지 않습니다.
간단하게 처리하기 위해서는 Activity를 상속받은 BaseActivity 클래스를 따로 만들어준 후 ArrayList<Activity>를 이용해서
추가된 Activity 들을 한번에 종료시켜주는 것이 가장 확실한 방법인 것입니다. 그럼 구현 하는 방법을 알아볼까요?
BaseActivity에 ArrayList<Activity>을 선언해줍니다.
public static ArrayList<Activity> actList = new ArrayList<Activity>(); |
그리고 A이동할 메소드에 해당 소스를 넣어줍니다.
actList 에 쌓인 Activity들을 for문을 돌려 모두 finish() 시켜버리는 것입니다.
for(int i = 0; i < actList.size(); i++) actList.get(i).finish(); intent = new Intent(C.this, A.class); startActivity(intent); finish(); |
이렇게만 해주면 제대로 동작하지 않습니다.
목적은 C와 A 사이에 있는 B를 제거하기 위함이므로 B를 actList 에 추가해줍니다.
onCreate()에서 추가해주면 됩니다.
//일단 B를 상속받고... public class B extends BaseActivity{ @Override protected void onCreate(Bundle savedInstanceState) { actList.add(this); // actList에 B를 추가해줍니다. super.onCreate(savedInstanceState); setContentView(R.layout.b); } } |
이렇게 만들어 놓고 필요시 for문을 돌려 Activity들을 언제든지 삭제할 수 있는 것입니다. ^^
=======================
=======================
=======================
출처: http://promobile.tistory.com/112
[Android] Activity 와 Stack Flag
▶ Activity와 Stack Flag
액티비티는 Activity Stack 이라는 것으로 관리되는데, 이 스택은 액티비티를 차곡차곡 쌓아두었다가 가장 상위에 있던 액티비티가 없어지면 이전의 액티비티를 다시 실행하도록 도와줍니다.
[Reference]
FLAG_ACTIVITY_SINGLE_TOP
FLAG_ACTIVITY_NO_HISTORY
FLAG_ACTIVITY_CLEAR_TOP
▶ FLAG_ACTIVITY_SINGLE_TOP
액티비티를 생성할 때 이미 생성된 액티비티가 있으면 그 액티비티를 그대로 사용하라는 플래그 입니다.
- 이미 만들어져 있는 액티비티를 다시 띄울 때의 인텐드 처리는 어떻게 할까요?
액티비티가 이미 메모리 상의 객체로 만들어져 있는 경우에는 액티비티를 다시 띄우더라도 onCreate() 메소드가 호출되지 않으므로 onNewIntent() 메소드를 재정의해 사용해야 합니다. onNewIntent() 메소드는 액티비티가 이미 객체로 만들어져 있을 때, 호출하는 액티비티로부터 전달되는 인텐드를 받아서 처리할 수 있도록 자동 호출됩니다.
[Reference]
public void onNewIntent(Intent intent)
▶ FLAG_ACTIVITY_NO_HISTORY
이 플래그로 설정하면 처음 이후에 실행된 액티비티는 액티비티 스택에 추가되지 않습니다. 즉, 플래그가 설정되어 있지 않은 경우에는 이전에 실행되었던 액티비티가 스택에 추가되므로 [Back] 키를 누르면 이전의 액티비티가 보이게 되지만 이 플래그를 사용하면 항상 맨 처음에 실행되었던 액티비티가 바로 보이게 됩니다.
▶ FLAG_ACTIVITY_CLEAR_TOP
이 액티비티 위에 있는 다른 액티비티를 모두 종료시키게 됩니다. 이 플래그는 홈 화면과 같이 다른 액티비티보다 항상 우선하는 액티비티를 만들 때 유용하게 사용할 수 있습니다. 이 플래그는 홈 화면과 같이 다른 액티비티보다 항상 우선하는 액티비티를 만들 때 유용하게 사용할 수 있습니다. 만약 홈 화면이 여러 개 있는 것이 아니라 하나만 만들어지는 것으로 하고 싶을 때 FLAG_ACTIVITY_CLEAR_TOP 플래그와 함께 설정하면 항상 하나의 객체가 메모리 상에 존재 하면서 그 상위의 액티비티를 모두 종료 시킬수 있습니다.
▶ 예제
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class SampleFlagIntentActivity extends Activity {
// 다른 activity를 띄우기 위한 요청 코드 정의
public static final int REQUEST_CODE_ANOTHER = 1001;
public static int startCount = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button startBtn = (Button) findViewById(R.id.startBtn);
startBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// 또 다른 Activity를 띄우기 위한 Intent 객체 생성
Intent intent = new Intent(getBaseContext(),
AnotherActivity.class);
intent.putExtra("startCount", String.valueOf(startCount));
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP
|
Intent.FLAG_ACTIVITY_CLEAR_TOP);
// Activity 띄우기
startActivityForResult(intent, REQUEST_CODE_ANOTHER);
startCount++;
}
});
startBtn.setBackgroundColor(0xffff0000);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
// 또 다른 Activity에서 보내온 응답인지 요청 코드로 확인
if (requestCode == REQUEST_CODE_ANOTHER) {
// toast message
Toast toast = Toast.makeText(getBaseContext(),
"onActivityResult called with code : " + resultCode,
Toast.LENGTH_LONG);
toast.show();
if (resultCode == 1) {
String name = data.getExtras().getString("name");
toast = Toast.makeText(getBaseContext(), "result name : "
+
name, Toast.LENGTH_LONG);
toast.show();
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class AnotherActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.another);
Intent receivedIntent = getIntent();
String startCount = receivedIntent.getStringExtra("startCount");
Toast.makeText(getBaseContext(), "startCount : " + startCount,
Toast.LENGTH_LONG).show();
// Button instantiated
Button returnBtn = (Button) findViewById(R.id.returnBtn);
returnBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// create a result intent and put extra value for "name" key
Intent resultIntent = new Intent(getBaseContext(),
SampleFlagIntentActivity.class);
resultIntent.putExtra("name", "mike");
resultIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP
|
Intent.FLAG_ACTIVITY_CLEAR_TOP);
// tell caller that we have succeeded and dispose this activity
setResult(RESULT_OK, resultIntent);
// finish();
startActivity(resultIntent);
}
});
}
public void onNewIntent(Intent newIntent) {
Intent receivedIntent = getIntent();
String startCount = receivedIntent.getStringExtra("startCount");
Toast.makeText(getBaseContext(),
"startCount at onNewIntent() : " + startCount,
Toast.LENGTH_LONG).show();
}
}
=======================
=======================
=======================
출처: http://surprisen.egloos.com/2511530
일반적인 경우, 안드로이드 용 어플리케이션을 작성하게 되면 여러가지 Activity 들을 생성하게 됩니다. 이때, 가장 골치가 아픈 일 중 하나는 바로 Activity 와 Activity 간의 Flow 를 설계하고 이를 적절하게 구현하는 일입니다. (특히 안드로이드를 사용해보지도 않은 UX 팀과 함께 일하게 되는 경우라면 더욱 그러합니다...)
기본적으로 안드로이드 플랫폼 상에서 Activity 는 또 다른 Activity 를 시작할 수 있고, 각각의 Activity 는 차곡 차곡 Task 라고 불리우는 Activity Stack 에 쌓이게 됩니다. 사용자는 일반적으로 Back 버튼을 이용해서 현재 화면상에 보이는 Activity 를 종료 시키고, 바로 직전에 사용된 Activity 로 돌아갈 수 있습니다. 안드로이드 펍의 회색님의 말을 빌리자면, 인터넷 브라우저를 통해 웹페이지를 검색하는 것과 유사한 방식입니다.
하지만 이러한 방법만으로는 효과적인 UX Flow 를 구축하는데 어려움이있습니다. 다행히, 구글에서는 Activity 를 호출할 때 사용되는 Intent 에 적절한 플래그 값을 설정해서 Activity Stack 을 제어할 수 있는 방법을 제공해 줍니다. 이 플래그들은 FLAG_ACTIVITY 라는 접두어를 갖고 있는데, 종류가 다양해 헷갈리는 수도 있는데, 개인적으로 제가 가장 요긴하게 사용하고 있는 FLAG_ACTIVITY 네 가지를 소개해 봅니다.
먼저 FLAG_ACTIVITY_SINGLE_TOP 입니다. 우선 간단하게 그림으로 표현해 보았습니다. A 와 B 두 가지 Activity 가 있는 데, A 라는 Activity 는 B 를 B 라는 Activity 는 다시 자기 자신인 B 를 호출 하는 경우라고 가정해 보겠습니다.
< FLAG_ACTIVITY_SINGLE_TOP >
호출하는 Activity B 가 이미 Task 의 가장 앞에 위치하는 경우, 또 하나의 B 를 생성하는 대신, 기존에 존재하는 B Activity 가 재활용됩니다. 이 때 B 가 재활용된다는 것을 개발자가 알아채고 새롭게 전달되는 Intent 를 사용할 수 있도록 B Activity 의 onPause() / onNewIntent() / onResume() 가 순차적으로 호출됩니다. 별 생각없이 동일한 Activity 를 여러번 생성하는 것은 메모리 사용량과 Activity 시작 속도 양쪽 모두에 악영향을 끼칠 수 있습니다. (특히 이미지가 덕지덕지 붙어 있는 Activity 라면). 이런 경우 FLAG_ACTIVITY_SINGLE_TOP 를 적절하게 활용하면 제법 큰 효과를 볼 수 있습니다.
두 번째는, FLAG_ACTIVITY_NO_HISTORY 플래그입니다. 우선 간단하게 그림으로 표현해 보았습니다. A 와 B 두 가지 Activity 가 있는 데, A 라는 Activity 는 B 를 B 라는 Activity 는 A 를 호출한 후 에 (A->B->A) 사용자가 Back 키를 누르는 경우를 가정해 보겠습니다.
<FLAG_ACTIVITY_NO_HISTORY>
말 그대로, FLAG_ACTIVITY_NO_HISTORY 로 설정된 Intent 로 시작된 Activity B 는 Task 에 그 흔적을 남기지 않게 됩니다. B 에서 또다른 A 를 시작한 후, Back 을 누르면 일반적인 경우 이전에 실행되었던 B 가 나타나지만, NO_HISTORY 를 사용하는 경우 맨 처음에 실행 되었던 A 가 화면에 표시됩니다. 몇 가지 주의할 점이 있습니다. 우선 NO_HISTORY 를 사용하게 되면 Task 에 해당 Intent 의 정보가 기록되지 않기 때문에, A->B 인 상황 (그림에서 두 번째 단계...) 에서 홈키등을 눌러 다른 Task 로 전환된 후, 다시 본 Task 로 돌아오게 되면, A Activity 가 화면에 표시됩니다. 또한, B Activity 의 onDestroy() 가 호출되는 시점이 조금 애매합니다.일반적인 예상과는 달리, B 에서 또다른 A Activity 를 호출하는 세 번째 단계에서는 onStop 까지만 호출되고, 이 후에 새롭게 호출된 A Activity 가 사라지는 순간 (네 번째 단계) 에서야 onDestroy() 가 호출 됩니다.
FLAG_ACTIVITY_NO_HISTORY 는 여러가지로 쓸모가 있는데, 특히 특정한 이벤트에 대한 알람등을 위해 다이얼로그 형태로 화면에 표시되는 Activity 들에 적용하기에 편리합니다. (대게의 경우 팝업은 해당 시점에 한번만 보여주면 되니까.)
다음으로 굉장히 유용한 플래그 두 가지를 동시에 설명해보고자 합니다.FLAG_ACTIVITY_REORDER_TO_FRONT 와 FLAG_ACTIVITY_CLEAR_TOP 플래그입니다. 우선 간략하게 그림으로 살펴 보겠습니다. A Activity 에서 B Activity 를 그리고 B 에서 A 를 호출하는 상황을 가정해보았습니다. (A->B->A)
FLAG_ACTIVITY_REORDER_TO_FRONT 는 매우 특이하게도 Task 의 순서 자체를 뒤바꿔 줍니다. 이 플래그를 사용하면, 런치하고자 하는 Activity 가 이미 Task 상에 존재하는 경우 해당 Activity 를 새롭게 생성하는 대신, 아래쪽에 위치한 Activity 의 순서를 Task 의 가장 위로 끌어올려줍니다. 따라서 A->B->A 의 순서로 Activity 호출이 일어날때, 새로운 A 가 생성되는 대신 아래쪽에 위치한 A 가 위로 올라와 최종적으로 B->A 의 형태로 Task 가 구성되게 됩니다. 어떤 Activity 에서 특정 Activity 로 점프하는 형식의 Flow 를 구성해야하는 경우 요긴하게 사용될 수도 있지만, Task 의 순서를 뒤섞는 다는 점에서 사용에 주의를 기울일 필요가 있습니다. (별 생각없이 남발하게 되면 Back 키가를 누를 때 엉뚱한 Activity 가 표시되어 사용자들이 굉장히 혼란스러워 하는 경우가 있습니다.)
마지막으로 소개해 드릴 플래그는 바로 FLAG_ACTIVITY_CLEAR_TOP 입니다. 제가 개인적으로 가장 사랑스럽게 생각하는 녀석입니다. 이 플래그가 사용되는 경우
런치하고자 하는 Activity 가 이미 Task 상에 존재하는 경우, 해당 Activity 위에 존재하는 다른 Activity 를 모두 종료시켜 줍니다. 따라서 A->B->A 로 호출이 일어나는 경우, B Activity 가 종료 되고, A Activity 만 Task 에 남게 됩니다. (A->B->C->A 인 경우에도 마찬가지로 B와 C 가 종료되고 A 만 남게 됩니다.)
이 Flag 는 특정 어플리케이션의 대쉬보드 (혹은 홈) Activity 를 호출할 때 굉장히 유용하게 사용될 수 있습니다. 즉 하나의 어플리케이션이 하나 혹은 두 가지의 주요한 Activity 와 그 외 특정 값을 선택하는등 단순한 일을 수행하기 위한 여러 개의 Sub-Activity 로 구성되어 있다면, 주요 Activity 를 호출하는데 이 Flag 를 사용함으로서 어플리케이션의 홈버튼등을 손쉽게 구현할 수 있습니다. 또 이 Flag 는 FLAG_ACTIVITY_REORDER_TO_FRONT 와는 달린 Task 의 순서를 뒤섞지 않음으로 사용자에게도 큰 혼란을 주지 않습니다. (사용을 적극 권장합니다.)
한 가지 주의해야할 점은 A->B->A 형태로 Activity 를 호출 하고자 할 때, 단순히 FLAG_ACTIVITY_CLEAR_TOP 만을 사용하게 되면, 기존에 생성되었던 A Activity 가 종료된 후 (onDestroy() 가 호출됨) 새롭게 A 가 생성 (onCreate()) 됩니다. 만일 기존에 사용된 A Activity 가 계속 사용되기를 원한다면, SINGLE_TOP 플래그와 함께 사용해야 합니다.
휴... 생각보다 내용이 길어졌네요. 대부분 SDK 문서를 읽어보면 잘 나와있는 내용이라 새로운 내용은 없습니다만... 문서 읽기를 게을리한 덕분에 한창을 고생했던 기억이 떠올라 (특히 CLEAR_TOP) 유용하게 사용한 Flag 를 정리하는 겸 작성해 보았습니다~
[출처] 안드로이드 알아두면 요긴한 FLAG_ACTIVITY 네 가지|작성자 휴
출처:[코딩] 안드로이드 유용한 Activity Flag들
=======================
=======================
=======================
출처: http://muzesong.tistory.com/38
안드로이드] 현재 액티비티, 다른 액티비티 종료하기
안드로이드를 하다보면 액티비티가 계속 쌓이는 경우가 있다. 이 경우는 시스템 적으로 아무래도
부담이되고, 물론 눈에 보일정도로 그런다기보다 계속 그렇게 쌓다보면 뒤로가기를 한참을 눌러야
밖으로 빠져나가게 되는 불상사가 생긴다.
이럴 경우 현재 액티비티나 현재액티비티가 아닌 다른 액티비티를 종료시켜서 액티비티를 줄이는
방법이있는데, 우선 현재 액티비티를 죽이는 방법은 간단하다.
어떠한 작업을 완료하고 액티비티를 종료하기를 원한다면 작업 완료 다음줄에
finish();
이것만 적어주면 된다. 이렇게 되면 저 함수를 만나는 즉시 현재 액티비티가 종료된다.
하지만 A 액티비티에서 B액티비티를 갔는데 A액티비티를 죽이고 싶다면 이렇게 하면된다.
우선 A 클래스에
public static Activity AActivity;
라고 스테틱으로 액티비티를 선언한다. 그리고 onCreate 안에
AActivity = Aclass.this;
이렇게, 액티비티 객체에 현재 클래스를 담아준다. 그럼 이제 B클래스로가서
Aclass aActivity = (Aclass)Aclass.AActivity;
이렇게 aActivity 라는 객체를 만드는데 그 객체는 Aclass의 스테틱변수인 AActivity를
넣어 둔다는 의미이다 보면 복잡해 보이는데 글로 쓰면 이렇다 .
A클래스 A클래스객체 = (A클래스)A클래스.A클래스에서 스태틱 액티비티 변수
이정도 순서이다. 헷갈리기 쉬울 것 같다.
그 다음 아래에 이렇게 만든 객체를 피니시하면된다
aActivity.finish();
이렇게 써주면 B클래스에서 아까 앞에 A액티비티를 종료 시킬 수 있다.
=======================
=======================
=======================
출처: http://www.androidpub.com/1857194
안녕하세요. 개발중 궁금한게 있엇 글남겨봅니다.
A -> B -> C 이렇게 Activity가 이동하고 있습니다.
이동 구조는
A -> B 상태에서 back키를 누를경우 A로 돌아가야되면
A -> B -> C 로 갈경우에는 A, B가 동시에 종료되어야 합니다.
현재
public static ArrayList<Activity> at = new ArrayList<Activity>(); 를 만들고
A, B Activity 에서
Utility.at.add(this);
이런 방식으로 Activity 를 더해주고
C Activity로 갈 경우
startActivity(intent);
int ActivitystackNum = Utility.at.size();
for (int i = 0; i < ActivitystackNum; i++) {
Utility.at.get(i).finish();
}
위와 같이 finish() 를 해주게 했습니다.
그런데 이렇게 한뒤 테스트를 해보았을때, 종료가 정상적으로 되지 않습니다...ㅠㅠ
제가 뭘 잘못한것일까요? ㅠㅠ
아니면 특정 Activity를 종료해줄수 있는방법이 있는것인가요?
고수분들의 조언부탁드립니다.
엮인글 주소 : http://www.androidpub.com/index.php?document_srl=1857194&act=trackback&key=405
2011.11.24 10:08:41
하이앤
각각의 액티비티가 안드로이트 액티비티 스택에 의존하지 않고 종료되도록 하는건 어떠세요?
A -> B 갈때 A 종료,
B에서 Back 시, A 호출
2011.11.24 10:12:04
어디없소
좋은 방법이기는하나....속도가 느려질수가 있어서요 ㅠ_ㅠ
2011.11.24 10:28:30
도카
해결책이 아닐수도 있지만, 위 상황처럼 A,B,C만 존재한다면 가능한 방법이 있긴 하겠네요
그냥 C 호출하실때
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
이거 설정하고 호출하시면 이전 스택에 액티비티가 모두 종료됩니다.
이거 단점이 기존 태스크를 사용하는게 아니고 다른 태스크를 띄우기때문에
경우에 따라서 액티비티 이동시에 좀 어색하게 이동할수도 있어요
2011.11.24 13:17:30
어디없소
감사합니다....그런데 A~C만 있는게 아니라서..ㅠ_ㅠ
그래도 새로운 방법을 알려주셔서
제 지식에는 도움이 되었습니다~
2011.11.24 11:29:46
wini
저같은 경우는 startActivityForResult 로 결과값에 따른 Activity종료를 해주고 있습니다.
Back버튼기능을 오버라이드해서 Result값을 짒어넣는 방식으로요.
2011.11.24 13:19:05
어디없소
제가 발코딩이라 ㅋ
지금 프로그래밍되어 있는구조에선 적용하기에 무리가 많이 따릅니다 ㅋ
2011.11.24 15:07:37
아즈라엘
제가 볼땐 무리 없이 잘 되야 하는 소스 입니다.
CotrollActivity.class 를 따로 만드시고 싱글톤 타입으로 생성자를 바꾸시는게 좋을것 같고요
내부에 ArrayList<Activity> 로 list Queue 를 가지고 있는 형태에서
원하는 놈만 꺼내서 피니쉬 시키는 형태로 하면 완벽할것 같습니다.
2011.11.24 17:08:39
어디없소
제 생각도 그렇다고 생각합니다...ㅋ
디버깅 해보았을때도 at.size(); 를 확인해보았을 경우에도 정상적으로 2개가 들어 있는거 같은데
finish() 가 호출이 되지 않는것 같습니다....;;;;
좀더 찬찬히 살펴보겠습니다~
2011.11.24 18:08:08
건방진프로그래머
모 제생각이지만 Task에 액티비티들이 쌓여있는데 중간것을 제거해버리면.... 문제가 될거 같은데요.
=======================
=======================
=======================
'스마트기기개발관련 > 안드로이드 개발' 카테고리의 다른 글
안드로이드 ListView 리스트 특정위치 이동 (0) | 2020.09.19 |
---|---|
안드로이드 android 시간 (시, 분, 초) 달력 날짜 관련 (0) | 2020.09.19 |
android 안드로이드 ndk jni stl 라이브러리 관련 (0) | 2020.09.19 |
adroid 안드로이드 Activity가 상태 관련 (0) | 2020.09.19 |
android 안드로이드 개발 - 종료 관련 (home, back키) (0) | 2020.09.19 |