TOMPA [Android] - 쓰레드와 서비스

2011. 9. 27. 21:27카테고리 없음

- 안드로이드는 기본적으로 멀티 스레드를 잘 지원한다. 기반인 리눅스가 본질적으로 멀티 스레드 운영체제인데다 주 개발 언어인 자바가 가상 머신 차원에서 멀티 스레드를 잘 지원하기 때문이다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 스레드는 고유의 스택을 가지며 메인 스레드와는 별도로 CPU 시간을 할당받아 실행된다. 스레드에서 할 작업은 run 메소드 안에 작성하는데 run 메소드가 스레드의 진입점이면서 메인 메소드이다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 스레드와 프로세스는 쌍으로 매치하지 않는다. (멀티스레드)tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 스레드는 뷰를 잡고 있지 않을 수 있는 방법을 제공한다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 스레드간 통신에서 루퍼가 필요하다. 스레드의 메시지를 처리하는 것이 핸들러이다.

- 백그라운드 스레드는 내부적인 연산만 해야 하며 다른 스레드 소속의 UI를 건드릴 수 없다.

1. 프로세스tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 컴포넌트가 실행되는 장소인 프로세스는 매니페스트 파일에 의해 제어가 된다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 컴포넌트가 가지는 엘리먼트인 <activity>, <service>, <receiver>, <provider>는 실행될 프로세스를 지정할 수 있는 속성이 있다. 각각의 컴포넌트가 자신만의 프로세스에서 실행될 수도 있고, 하나의 프로세스를 공유할 수도 있으며, 동일한 프로세스에서 다른 어플리케이션의 컴포넌트가 실행되도록 할 수도 있다. 따라서 <application> 엘리먼트는 모든 컴포넌트가 값 설정을 위한 속성을 가지고 있다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 모든 컴포넌트는 지정된 프로세스의 메인 스레드에서 인스턴스화되며, 그 컴포넌트를 호출하는 시스템은 메인 스레드로부터 시작된다. 주의할 점은 각각의 인스턴스 별로 따로 스레드가 생성되지 않는다는 점이다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 따라서 오래 걸리는 작업은 백그라운드에서 별도의 스레드에서 처리해야 한다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 하나의 프로세스는 여러 개의 스레드를 소유할 수 있으며, 프로세스 자체는 껍데기일 뿐이고 사실은 스레드가 모든 명령을 수행한다.

2. 루퍼 (Looper) p.856tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 루퍼는 메시지 큐에서 메시지를 꺼내어 핸들러로 전달하는 작업을 수행한다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 메인 스레드의 경우 기본적으로 루퍼를 가진다. 하지만 일반 작업을 수행하는 스레드의 경우 기본적으로 루퍼를 가지지 않는다. 만약 이런 스레드가 메시지를 받아야 할 경우 루퍼를 직접 생성 시켜야 한다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- prepare() : 현재 스레드를 위한 루퍼를 준비한다. loop() : 큐에서 메시지를 꺼내 핸들러로 전달하는 루프를 실행한다. quit() : 루프 종료

getThread() : 루퍼와 연결된 스레드를 구한다. getMainLooper() : 주 스레드의 루퍼를 구한다. myLooper() : 현재 스레드의 루퍼를 구한다.

- 스레드가 초기화되는 run 메소드에서 prepare를 호출하여 메시지 큐를 준비하고 핸들러 객체를 생성한다. 핸들러를 멤버로 선언하면 주 스레드에서 작업 스레드 생성시에 핸들러가 같이 생성되며 이 때는 스레드의 루퍼가 준비되지 않은 상황이므로 주 스레드의 루퍼에 붙어 버린다.

그래서 작업 스레드에서 prepare를 호출하여 메시지 큐를 먼저 준비시킨 후에 핸들러를 생성해야 한다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 오해하지 말 것은 메시지는 스레드 간의 통신 장치일 뿐이라는 점이다. 안드로이드는 시스템 전역적인 메시지 큐를 제공하지 않으므로 메시지를 통해 응용 프로그램끼리 통신할 수는 없다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 정리 : 스레드 간의 통신은 메시지를 통해서 하게 되는데 각각의 스레드에는 메시지 큐가 있다. 메인스레드에서는 이 메시지 큐에서 메시지를 꺼내어 핸들러로 전달하는 루퍼가 존재하지만, 일반 작업 스레드는 루퍼가 존재하지 않아서 개발자가 직접 생성해줘야 한다.

3. 핸들러tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- Handler 클래스로 표현되는 핸들러는 스레드 간에 메시지나 러너블 객체를 통해 메시지를 주고 받는 장치이다.

- 핸들러는 항상 하나의 스레드와 관련을 맺는데 자신을 생성하는 스레드에 부착되며 그 스레드의 메시지 큐를 통해 다른 스레드와 통신한다.

- 보통 다른 스레드로부터 전달되는 메시지를 수신하지만 자기 자신이 보낸 메시지도 물론 받을 수 있다.

- 메시지가 도착하면 핸들러의 handleMessage(Message msg) 메소드가 호출되며 이 메소드를 통해 메시지를 수신한다. 메시지는 스레드 간의 통신 내용을 저장하는 객체이다. 단순한 신호나 명령뿐만 아니라 복잡한 추가 정보도 전달 받아야 하므로 여러 개의 필드를 가진다.

- int what : 메시지의 의미, int arg1,arg2 : 메시지의 추가정보, Object obj : 정수만으로 메시지를 기술할 수 없을 때 임의의 객체를 보낸다.

Messenger replyTo : 메시지에 대한 응답을 받을 객체를 지정한다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 메시지를 보내는 쪽에서는 전달하고자 하는 내용을 Message 객체에 저장하여 핸들러로 전송한다. 이때는 다음 메소드를 사용한다.

Handler.sendEmptyMessage(int what);tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

Handler.sendMessage(Message msg);tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

sendMessageAtFrontOfQueue(Message msg); p.849***tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 메시지를 보내는 대신 post(Runnable r) 메소드로 Runnable 객체를 보낼 수도 있다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 메시지는 어떤 작업을 하라는 지시사항을 보내는 것인데 비해 러너블은 작업을 직접 수행하는 코드라는 점이 다르다. 핸들러로 러너블을 보내면 러너블의 run 메소드가 실행된다. p.851tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

작업 스레드 내에서tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

mHandler.post(new Runnable(){tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

public void run(){tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

~~~~~~~~~ }});tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

와 같이 되어 있고 메인 스레드의 핸들러는tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

Handler mHandler = new Handler(); 와 같이 되어있는 경우tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

핸들러는 메시지를 직접 처리하지 않으므로 handleMessage 메소드를 굳이 정의하지 않아도 상관없다. 그냥 존재하기만 하면된다. 만약 메시지도 처리하고 러너블도 받아들인다면 handleMessage 메소드를 정의해야 할 것이다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

* 주의할 것은 위 코드에서 러너블 객체를 생성하는 코드가 작업 스레드 내에 있지만 이 러너블을 실행하는 주체는 메인 스레드라는 점이다.

- 액티비티 밖에 작업 스레드가 존재 한다면 메인스레드는 신호를 받기 위해 작업 스레드에게 핸들러를 전달해야 한다. 스레드의 생성자로 전달하는 것이 가장 쉽고 간편하다. 작업 스레드는 생성자로 전달받은 핸들러를 자신의 멤버에 저장해 둔다. 여러 액티비티가 공유해야 하는 일반적인 작업이라면 이와 같은 형태로 작성하면 된다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 서로 통신할 때마다 매번 Message 객체를 new 연산자로 새로 생성하면 메모리도 많이 소모할 것이고 속도도 느려질 것이다. 그래서 안드로이드는 시스템에 메시지 풀을 두어 캐시를 유지한다. 시스템의 메시지 풀에서 메시지 객체를 꺼낼 때는 다음 메소드를 사용한다.

Message obtain(Handler h, int what, int arg1, int arg2, Object obj)tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

recycle()tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- obtain 메소드는 메시지 풀에서 비슷한 메시지를 꺼내 재사용한다. 인수없이 obtain을 호출하면 풀에서 빈 메시지 객체 하나를 꺼내주는데 어쨋거나 new 연산자로 하는 것보다 빠르다. 인수를 전달하면 메시지 객체를 꺼낸 후 객체에 값을 대입해 주기도 하므로 꺼냄과 동시에 매시지 객체게 값을 대입해 넣을 수도 있다.

- 매 통신시마다 사용하는 메시지들이 비슷비슷하므로 한번 사용된 Message 객체는 캐시되어 있을 확률이 아주 높으며 매번 생성하는 것보다 캐시된 것을 재사용하는 것이 성능에 유리할 것이다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- recycle() 메소드는 사용한 메시지를 풀에 다시 집어 넣는데 풀에 들어간 메시지는 이후부터 시스템이 관리하므로 더 이상 건드려서는 안된다.

4. ANR (Application Not Responding)tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 응용 프로그램이 5초 이상 사용자의 입력에 반응하지 않을 때, 브로드캐스트 리시버가 10초 내로 리턴하지 않을 때를 발견하면 시스템은 ANR 대화상자를 띄우며 이 대화상자에서 프로그램을 강제로 죽여 버릴 수도 있다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- ANR을 방지하는 일반적인 해법은 시간이 걸릴만한 작업을 스레드로 분리하는 것이다. 또는 비동기적인 호출을 통해 내부에서 알아서 스레드를 돌리도록 유도해야 한다. 스레드는 꼭 다중 작업을 위해서만 사용되는 것이 아니라 반응성을 높이는 데도 아주 유용하다. 안드로이드 프로그램은 기본적으로 싱글 스레드 구조인데 5초가 넘는 작업은 무조건 스레드로 빼고 메인은 항상 사용자의 입력을 대기해야 한다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 장시간 걸리는 작업은 스레드로 분리, 작업이 끝난 후 할 일은 핸들러로 분리tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 최적의 반응성을 얻으려면 메인 스레드는 디스크 입출력이나 네트워크 액세스를 아예 하지 않고 사용자의 입력만 대기하는 것이 가장 이상적이다.

4-1. StrictModetompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 어떤 동작을 금지할 것인지를 지정해 놓고 위반하는 코드가 발견될 경우 즉시 조치를 취하는 것이다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 스레드 내부의 직접적인 동작뿐만 아니라 다른 서비스나 CP를 호출할 때도 감시를 한다는 점에서 강력하다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

4-2. LongTimetompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 복잡한 연산처럼 본질적으로 오래 걸리는 작업들이 있다. 스레드로 작업을 분리해도 반응성만 좋아질 뿐이지 작업시간이 단축되는 것은 아니다. 어디까지 진행중 이라는 것을 사용자에게 주기적으로 보고하고 중간에 취소도 가능해야 한다.

- 프로그래스 대화상자를 사용하면 작업경과를 깔끔하게 출력할 수 있다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

4-3. AsyncTasktompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 백그라운드 작업을 하기 위해서는 스레드, 핸들러 등을 각각 만들어야 하고 작업 중에 핸들러를 주기적으로 호출해야 하는 번거로움이 있는데 이 작업을 대신 수행해 주는 도우미 클래스이다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

4-4. BackWorktompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 프로그래스를 메인이 출력하고 작업을 스레드가 담당하게 되면 굉장히 번거롭다. 반대로 뒤집어서 작업은 메인이 처리하고 프로그래스 처리를 스레드가 맡으면 좀 더 단순해지며 재활용성도 높아진다.

- 백그라운드에서 처리할 코드 앞뒤로 스레드 시작, 끝 명령만 작성하면 된다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 스레드에서 프로그래스를 구현할 때 동작하게 하려면 주기적으로 다시 그리기를 해야 한다. 즉, 스레드가 메시지를 처리할 수 있어야 한다는 얘기다. 그래서 run 메소드에서 Looper.prepare 메소드를 호출하여 루퍼를 초기화하고 loop 메소드로 메시지를 퍼다 나르도록 해야 프로그래스 대화상자의 애니메이션이 진행된다. ( 메시지 루프를 종료하지 않으면 해당 스레드는 언제까지고 계속 실행될 것이다.) p.897

5. Servicetompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 서비스는 백그라운드에서 실행되며 사용자와 직접적인 상호작용은 하지 않는다. 전면에서 사용자를 대면하는 액티비티를 위해 연산이나 메소드 등의 서비스를 제공하는 것이 주된 임무이다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 클라이언트에서 어떤 식으로 호출하는가에 따라 다음 두 가지 사용방법이 있다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

1. 백그라운드 데몬 : 배경에서 계속 실행되는 프로세스이다. 클라이언트가 기동시켜 놓기만 하면 사용자의 명령이 없어도 지속적으로 실행된다. MP3 플레이어가 대표적인 예인데, 화면에 보이지는 않지만 배경에서 노래를 계속 재생한다. 전통적인 의미의 서비스에 가장 가까운 형태이다.

2. 원격 호출 인터페이스 : 클라이언트를 위해 특정한 기능을 제공하는 역할을 한다. 자신의 기능을 메소드로 노출시키며 클라이언트는 메소드를 호출함으로서 서비스를 이용한다. 다른 운영체제의 COM,CORBA에 대응되는 개념이다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 사용 형태가 조금 다르지만 둘 다 Service 클래스를 파생시켜 작성한다. 두가지 형태를 모두 지원하는 서비스도 만들 수 있다.

- 사용 용도에 따라 가장 뚜렷한 차이가 발생하는 부분은 서비스의 생명주기이다. 시작할 때 onCreate(), 종료될 때 onDestory() 메소드가 호출되는 것은 동일하지만 중간에 호출되는 메소드가 다르다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 데몬일 때는 백그라운드 서비스를 시작하라는 onStartCommand() 메소드가 호출되고, 원격 호출일 때는 클라이언트에게 인터페이스를 노출하는 onBind() 메소드가 호출된다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 서비스가 어떤 식으로 사용될 것인가는 클라이언트가 어떤 메소드로 서비스를 기동시키는가에 의해 결정되며 서비스는 자신이 어떻게 사용될지 미리 알 수 없다. 따라서 생명주기의 4개 메소드는 일단 모두 정의해야 하며 각 메소드는 꼭 필요한 동작만 해야한다. 원격 호출로 사용된다면 백그라운드 동작은 준비할 필요가 없으므로 onCreate에서는 최소한의 초기화만 해 놓고 나머지 초기화는 IBinder onBind()에서 처리한다. 설사 데몬으로 사용된다 하더라도 기동될 때인 int onStartCommand에서 실행 준비를 해야하며 onCreate에서 미리 준비할 필요는 없다.

- 서비스는 응용 프로그램을 구성하는 컴포넌트 이므로 매니페스트에 등록해야 한다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 서비스는 백그라운드에서만 동작하며 스스로 기동하지 못하므로 클라이언트가 있어야만 한다. 누군가가 불러주지 않으면 아예 그 존재 자체가 사용자에게 보이지 않는다. 클라이언트에서 서비스를 시작 및 중지할 때는 다음 메소드를 호출한다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

ComponentName startService(Intent service)tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

boolean stopService(Intent service)tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

5-1. 원격 인터페이스tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 클라이언트에게 자신의 메소드를 제공하려면 자신의 메소드 목록을 인터페이스로 정의해야 한다. 이는 단순히 메소드의 원형을 선언하는 것과는 수준이 다른데 원격에서 호출되는 메소드는 응용 프로그램의 경계를 넘어서 인수를 전달해야 하는 어려움이 있다. 각 응용 프로그램이 사용하는 메모리가 완전히 분리되어 있어 통상의 방법으로는 인수를 넘기기 어렵다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 전달할 수 있는 인수의 종류가 자바 기본타입과 Parcelable 정도로 제한되며 그 외에도 몇가지 제약이 존재한다.

- 자바 수준에서 인터페이스를 직접 정의하기는 대단히 어렵다. 안드로이드는 원격 인터페이스를 정의하는 AIDL(Android Interface Definition Language) 이라는 별도의 언어를 제공하며, AIDL 컴파일러가 인터페이스 정의를 구현하는 스텁까지 생성해 준다. AIDL 소스를 작성하여 프로젝트에 포함시켜 놓으면 AIDL 컴파일러가 이 인터페이스를 구현하는 자바 파일을 생성하여 gen 폴더에 배치한다.

- .aidl의 확장자를 가지는 인터페이스 소스에 메소드의 원형을 선언한다. 실제 연산을 하는 코드는 서비스에서 채워 넣어야 한다.

- 인터페이스를 상속받는 객체를 생성하고 메소드를 구현하여 onBind()에서 리턴한다. p.1161

- 생성된 mBinder 객체를 onBind에서 리턴하면 클라이언트는 mBinder 객체를 통해 서비스의 메소드를 호출할 수 있다.

- 클라이언트에서 서비스에 연결하거나 해제할 때는 다음 메소드를 호출하여 바인딩 한다.

boolean bindService(Intent service, ServiceConnection conn, int flags);

void unbindService(ServiceConnection conn);tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

첫 번째 인수는 사용하고자 하는 서비스를 지정, 두 번째 인수는 서비스가 연결, 해제될 때의 동작을 정의하는 연결 객체이다. 서비스를 사용하는 클라이언트는 ServiceConnection 인터페이스를 구현해야 하는데 클라이언트와 서비스가 연결되거나 해제될 때 호출되는 메소드를 정의한다. 마지막 인수는 서비스 바인딩 방식을 지정하는데 통상 BIND_AUTO_CREATE로 지정하여 자동으로 기동시킨다.

- 서비스가 연결될 때 onServiceConnected 메소드가 호출되며 이 때 인수로 전달되는 binder 객체를 스텁의 asInterface 메소드로 전달하면 원격지 서비스 객체를 구할 수 있다. 이후 이 객체의 메소드를 호출함으로서 서비스의 기능들을 사용한다. p.1164

- 아주 복잡한 연산이나 통계 처리 등을 서비스에 작성해 놓으면 여러 응용 프로그램이 기능을 공유할 수 있다는 이점이 있다.

- 서비스는 응용 프로그램끼리 공유할 수 있으므로 외부 패키지에서도 호출할 수 있다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 여러 개의 클라이언트가 동일한 서비스를 바인드 하는 것도 가능하다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof


6. IntentServicetompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- onHandleIntent(Intent intent)tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

7. 액티비티 생명 주기에서 bind 서비스 방법tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- onResume()에서 bindService() 메소드를 호출한다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- onPause()에서 unbindService() 메소드를 호출한다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 오른쪽 그림 참고tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

8. 별도의 프로세서로 동작 시키는 방법tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- android:multiprocess="true"|"false" 속성 사용

- 일반적으로 activity instance는 그것을 정의한

어플리케이션과 같은 프로세스에서 launch 된다.

만약 이 속성 값이 true라면, 해당 instance는 원래의tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

어플리케이션 프로세스가 아니라 launch 시킨 곳에서

작동한다.tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

9. Parcelable 인터페이스tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof

- 사용자에 의해 정의되는 자료형을 알수 없는 객체를 생성 후 액티비티 간에 전달하고자 할 때 사용한다.

- CREATOR라는 Parcelable.Creator 객체를 만들어 줘야 한다. tompa 모바일 프로그래밍 능력 시험 안드로이드 marcof