오늘은
 안드로이드의 내부-인텐트, 애플리케이션 구성요소, 액티비티 수명주기등을 알아보도록 할께요.

아 그전에 아직 테이블 레이아웃을 보지 않았으니깐 잠깐 알아보고 갈께요. 스크롤뷰도요





만약 어플리케이션이 죽는다면, DDMS의 logcat을 분석해서 디버그를 할 수 있어요.



xml파일에 있는 리소스를 가져오도록 해 볼께요







안드로이드 개발에 있어서 가장 주용한 개념인 intent라는 게 있어요. 뭔가 하려고 하는 일, 즉 어떤 작업을 할건지 담아놓은 객체죠
인텐트의 구성요소로 액션, 데이터, 카테고리가 있는데요, 액션은 어떤동작을 할지 정하는 것으로 ACTION_VIEW는 보겠다,
ACTION_EDIT는 편집을 하겠다는 걸 뜻해요.
 데이터는 하려는 일을 하는 데이터를 나타낸건데 Uri로 표현이 되요. Uri는 URL같이 표시되죠. 그런데 URL과 다른점은 
URL은 우리가 읽기 쉽게 표현되 있는거고, Uri는 시스템이 읽기 쉽게 표현되 있는거에요. 그래서 Uri.parse() 함수를 사용해
우리가 읽기 쉬운 URL을 시스템이 읽기 쉬운 Uri로 바꿔주죠.
 Uri를 지정할 때 content: 이렇게 쓰는데요 이렇게 적어줌으로써 시스템이 액션과 데이터를 조합하여 Activity를 보여주게 되죠. 
  액션과 데이터를 적어주지 않고 컴포넌트 이름을 적어줄 수도 있는데요, Activity를 직접지정하는 거죠. 시스템은 pakage이름을 보고
특정 App를 찾아간후, Class이름으로 특정 class를 찾아가요. 이걸 바로 명시적 인텐트라고 하고, 액션이나 데이터를 사용하는 걸 
암시적 인텐트 라고 해요.
 category는 특정 컴포넌트에 대한 부가적인 정보를 여기 넣어준다고 생각하면 될 거 같애요.
 이런 인텐트는 다른 App간에 서로의 App를 띄우는 모든 경우에 사용되고요, 컴포넌트와 컴포넌트 간 데이터를 전달할때 전부
인텐트가 들어가죠. 
 하나의 App는 하나의 VM에서 돌아가요. 그리고 리소스를 공유하죠. 

Activity에 대한 category를 넣어줄 수 있습니다. 추가적인 정보를 말하죠. 예를 들어 category의 이름이 CATEGORY_LAUNCHAR면
시스템은 이 인텐트필터를 포함하는 액티비티를 홈 스크린에 보여줘요.



Activity가 어떤 동작에 관심이 있는지 설정하기 위해 intent-filter를 만들수 있어요. 인텐트 필터는 시스템에 있는 Activity Manager에게
이 Activity는 어떤 인텐트에 대해 관심이 있고, 그 인텐트가 들어오면 어떤 동작을 할 지 알려주죠. 예를들어 이 안에 '나는 VIEW 액션과 http 데이터가 들어오는 인텐트를 받아들일 수 있는 Activity다!! ' 하고 명시해 줄 수 있어요.



처음 시작될 Activity를 바꿀수도 있어요
여기서 알고가야 할게 있는데요, 하나의 사용자 시나리오를 처리하는 데 하나의 App로만 구성된 건 아니라는 거죠. 예를들어 
그림편집을 하고 메일로 보내는 시나리오가 있다면 그림편집 App에서 '그림선택 App'를 사용하고, 메일 보낼때는 'gmail App'
를 사용해요. 이렇게 사용되는 Activity의 묶음을 task라고 하죠. 각각의 App는 각각의 process를 갖고 있어요. 새로운 App가 
나타날 때마다 Activity stack에 쌓이게 되죠.
 인텐트의 중심에는 Activity Manager가 있어요. 얘가 한쪽 App에서 intent를 받고 다른 App를 실행시켜 주죠. 인텐트를 만들면
시스템에 등록을 해 줘요. 그럼 시스템이 수집을 해서 실제 intent 요청이 왔을 때 적당한 Activity에 매칭을 시켜줘요.
 이게 바로 안드로이드에서 멀티태스킹의 핵심이에요. 여러개의 task랑 프로세스가 잘 돌아가게 만들어 놓았죠. 



인텐트를 사용하는 모습들이에요. 인텐트를 띄운 결과를 알고싶을 때 startActivityForResult 함수를 사용하죠.











그런데 인텐트를 사용해 전화를 걸려고 하면 어플리케이션이 종료되버려요. 퍼미션이 없기 때문이죠. 그래서 퍼미션을 설정할 수도 있습니다. 퍼미션으로 App가 접근할 수 있는 영역을 정할 수 있어요.





Activity간에 데이터를 전달할수도 있어요
Activity가 무엇일까요? 액티비티는 보통 하나의 화면을 표현하죠. 그려주기도 하고, 입력도 받고 해요. 액티비티를 사용하므로써
컴포넌트 재사용을 할 수 있죠. 이전에 실행된 액티비티는 차곡차곡 스택에 쌓이기 때문에 스택에 있는게 pop되면서 재사용
할 수 있어요. 이렇게 액티비티가 여러개 쌓여서 실행되는 걸 task라고 하죠. 여러 App가 상호연동하면서 동작하게 되요. 
 Activity간 데이터를 전달할 때는요 A란 Activity는 putExtra() 로 데이터를 집어넣어서 B에게 전달하고, B는 getExtra()로 데이터를 
가져오죠. B는 Activity 상태값을 돌려줄 수도 있어요.

 인텐트는 데이터 전달을 위해서만 쓰일수도 있어요. 결과값이 올 때 Callback 메소드가 호출이 되죠. 결과값을 받기를 원하면 
startActivityForResult(~~, code) 함수를 이용해서 인텐트를 전달하면 되요. 여기서 code를 왜 주냐면요 인텐트를 전달하는 
A라는 Activity는요 액티비티 B 뿐만 아니라 다른 액티비티인 C를 호출할 수도 있기 때문이에요. 그래서 서로 구분해 주기 위해 
code를 쓰죠.









manifest파일의 역할에 대해서 조금 알아보고 넘어갈께요.
App의 자바 패키지 이름을 지정해요. 패키지는 시스템 상에서 유일하게 구분되는 이름이죠.
App의 컴포넌트에 대해서도 시스템에게 설명해줘요. 컴포넌트에는 액티비티, 서비스, 브로드캐스트 리시버, content provider
가 있죠.
App가 가져야 하는 권한에 대해서도 나와있어요. 다른 App가 접근할 때의 권한에 대해서도 나와있죠.
안드로이드 버전이 워낙 여러개라서 API의 최소레벨도 나와있어요.
그리고 App에 필요한 라이브러리 리스트도 나와있죠.
원래는 하나의 App가 하나의 Process에 매핑이 되는데 가끔 사용하는 프로세스를 변경해서 써야 할 경우도 생기게 되요.
그럴때는 '이 서비스는 따로 20M의 process를 써라' 라는 정보도 넣어줄 수가 있죠.
manifest파일에 있는 intent-filter 엘리먼트는요 이 컴포넌트가 어떠한 상황에서 호출이 될 껀지 결정해줘요.

 어플리케이션엔 수명주기라는 게 있는데요 시스템이 스스로 관리하는거죠. 시스템은 사용자가 process에 대해 신경슬 필요없도록
알아서 판단해서 process를 관리해요. 안드로이드에 종료버튼이 없는 이유이기도 하죠. 시스템은 메모리를 확보하기 위해서
App process를 죽이는데요 그냥 죽이는 건 아니고 중요하지 않은 순서로 제거해요. 포커스가 있는 애는 제일중요한 애고
포커스는 없지만 보이고 있는 애는 그 다음으로 중요한 애고, background로 stack에 존재하는 애는 덜 중요한 애이죠. 그리고
특정 컴포넌트가 실행할 때 알아서 프로세스를 올려줘요. 프로세스는 그래도 죽을때 죽는다고 얘기는 하고 죽죠.
 새로운 Activity가 시작되면 스택의 맨 위쪽에 넣어지고 그 전에 있던 애들은 하나하나씩 없어지면서 밑으로 가요. 얘네는
언제든지 메모리에서 사라질수 있는 애들이죠. 주의할 점은 프로세스가 사라진다고 stack에서 사라지는 건 아니라는 거에요.
 
 액티비티는 수명주기를 가져요. Running, Paused, Stopped, Destroyed 이렇게 4개가 있는데요
Running은 포커스를 가진상태이고
Paused는 포커스를 잃은 상태이고 화면에는 보이는 중이죠.
Stopped은 화면에도 보이지 않고 stack에 쌓여있는 상태에요.
Destroyed는 메모리에도 남아있지 않고 사라지는 거죠.

 액티비티는 처음에 생기면 OnCreate() 가 호출되요.
그리고 OnStart() 에 의해 화면에 보이게 되죠.
OnResume() 으로 포커스를 가지게 되요.
여기까지 하면 Running상태가 되죠.
Running에서 onPause() 가 호출되면 Paused 상태가 되면서 포커스를 잃게되요.
하지만 다시 onResume() 로 포커스를 얻을 수 있죠.
Paused 상태에서 onStop() 이 호출되면 화면에도 보이지 않고 스택에 쌓여 있기만한 Stopped 상태가 되죠.
여기서 다시 Running으로 가서 포커스를 잡으려면
onRestart() 를 호출하고 --> onStart() 로 화면에 보인 후 --> onResume() 으로 포커스를 잡아야 해요.
 이렇게 액티비티가 화면에 보여지는 생애기간은 onStart() 메소드를 호출할 때부터 onStop() 메소드를 호출할 때까지
라고 할 수 있죠.

 그럼 onCreate() 부터 볼께요
여기서는 setContentView() 를 이용해서 화면구성을 해요. 그 다음에 Intent에서 받아온걸 처리하죠. 
 onPause() 는 포커스를 다른 Activity에게 넘기는 거에요. 내께 다 끝나서 stack의 top이 실행되어 새로운게 덮어씌여지는거죠.
 얘는 주로 데이터를 저장소에 저장하거나 할때 많이 쓰여요. 그리고 이 상태의 Activity는 시스템이 강제로 종료시킬수도 있는데요
그래서 Date를 저장소에 저장해야 하는거에요.
 onPause() 와 onResum() 은 새로운 Activity가 올라오거나 사라지는 거기 때문에 사용자가 부드럽게 느끼려면 시간을 짧게 해야
해요. 
 onDestroy() 는 액티비티가 없어지기 전에 호출이 되요. 더이상 Activity가 쓸모가 없어진 거죠. back키를 눌렀을 때 호출이 되죠.
 즉, onPause(), onStop(), onDestroy() 메소드가 강제종료될 수 있는 애들인데요 onPause() 만이 강제종료되기 전에 확실히
호출되는 메소드이고 onStop(), onDestroy() 메소드는 호출되지 않을수도 있기 때문에 데이터 저장등의 코드는 꼭 onPause()
에 있어야 해요.
 새로운 액티비티가 덮어 씌어지는거랑 다이얼로그랑은 전혀 틀려요. 다이얼로그가 떴을 때 상태변화는 전혀 없죠.
 반투명 윈도우로 액티비티를 보여줄 수도 있는데요 이렇게 되면 새로운 Activity가 올라오긴 하는데 반투명상태라서 예전 Activity도
보이긴 하죠. 근데 입력을 할순 없고요. 
 back key와 home key를 눌렀을 때 차이가 좀 있어요.
 back key를 눌렀을 때는 Activity를 종료시키는 거고요 home key를 눌렀을 때는 사용할 여지를 남겨놓는거죠. 그래서 스택에도
Activity가 쌓인 채로 있는데요, 만약 A 에서 B 를 호출하고 home key를 누른 후 다시 들어오면 A부터 실행되는게 아니라 B가
실행이 되는거죠.
 그리고 phone에서 stop버튼 누르면 대기상태로 갔다가(paused) 다시 menu버튼을 누르면 resume이 되요.
 지금까지 본것처럼 Activity를 보여줄 때는 stack에 올라가는가? 화면에 보여져야 하는가? 포커스를 가져야 하는가? 등을 신경
쓰는게 중요해요.
 안드로이드에서의 바탕화면은 window의 바탕화면과 틀려요. 내가 하던 App위에 바탕화면 App를 덮어 씌었을 뿐이죠.
 

Activity 데이터 교환을 이용한 예제예요






 시스템에 메모리가 없어서 프로세스를 갑자기 죽일 때는요 그냥 죽이는건 아니고 saveInstanceState() 와 restoreInstanceState()가
호출이 되요. saveInstanceState()는 현재 상태를 저장해야 하는 시점에 불리게 되죠. restoreInstanceState()는 파일에 저장되있던 값
을 되돌려 놓으라는 거에요. 이게 호출될 때는 Activity가 스택에 있다해도 다시 불릴때 create부타 다시하죠.

 아래는 두 Activity를 이용해 수명주기를 확인하는 예제에요



 
신고

'T아카데미' 카테고리의 다른 글

사용자인터페이스_02  (0) 2010.07.02
사용자인터페이스_02  (0) 2010.07.01
어플리케이션 구조  (0) 2010.07.01
사용자인터페이스_01  (0) 2010.07.01
안드로이드 개발환경  (0) 2010.06.27
안드로이드 개요  (0) 2010.06.26
Posted by 응큼미소


티스토리 툴바