Transcript ch06-1

스레드와 애니메이션
2011010907 김잔디
Contents
핸들러
자바의 스레드
메시지 전송하여
Runnable 객체
• 06-1
사용하기
사용하기
실행하기
실행하기
스레드만들기
메인
스레드
스레드
#1
화면에 보여주기
메인
스레드
뷰
스레드
#1
Runnable객체로 실행하기
메인
스레드
뷰
스레드
#1
Runnabl
e
스레드란?
스레드(Thread) : 하나의 프로그램 내에서 여러 개의 실행 흐름을
두기 위한 모델.
스레드는 광범위 하게 사용되며, 자바에서 사용되던 것들이 그대로
사용.
자바와 안드로이드 스레드의 유일한 차이점이 다양한 기능을 만들
어 낸다.
I. 핸들러 사용하기
멀티스레드
메인 스레드
 메인 엑티비티
- 애플리케이션이 실행될 때 하나의 프로세스에서 처리
- 이벤트를 처리하거나 필요한 메소드를 정의하여
기능을 구현하는 경우에도 동일한 프로세스 내에서 실행
공통메모리
리소스
(1) 프로젝트 생성 시
스레드
#2
메인
스레드
#1
스레드
 문제점
- 대기시간이 길어지는 네트워크 요청 등의 기능을
수행할때는 화면에 보이는 UI도 멈춤 상태로 있게 됨
 해결방안
- 하나의 프로세서 안에서 여러 개의 작업이 동시 수행
되는 멀티 스레드 방식을 사용
공통
메모리
리소스
(2) 별도의 스레드 생성 시
[멀티 스레드 시스템에서
공통 메모리 리소스 접근 ]
 멀티 스레드
- 같은 프로세스 안에 들어 있으면서 메모리 리소스를
공유하게 되므로 효율적인 처리가 가능
- 동시에 리소스를 접근할 경우 데드락(Dead lock)발생
핸들러 사용하기
서비스 사용하기
백그라운 작업은 서비스로 실행하고 사용자에게는 알림 서비스를 이용해 알려
줍니다. 만약 메인 액티비티호 결과값을 전달하고 이를 이용해 다른 작업을 수
행하고자 한다면 브로드 캐스팅을 이용해 결과 값을 전달 할 수 있습니다
스레드 사용하기
스레드는 동일 프로세스 내에 있기 때문에 작업 수행의 결과를 바로 처리할 수
있습니다. 그러나 UI객체는 직접 접근 할 수 없으므로 핸들러(Handler) 객채를
사용 합니다.
II. 자바에서 스레드 사용하기
표준자바에서 스레드 사용방법
public class MainActivity extends Activity {
private int value = 0;
private boolean running = false;
TextView textView01;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView01 = (TextView) findViewById(R.id.textview01);
}
Button showBtn = (Button) findViewById(R.id.showBtn);
showBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
textView01.setText(“Value from thread : " + value);
}
});
 스레드는 new연산자를 이용하여 객체를
생성한 후 start()메소드를 호출하면 시
작함
 Thread 클래스에 정의된 생성자는 크게
파라미터가 없는 경우와 Runnable 객체
를 파라미터로 가지는 두가지로 구분함
1. Value에 할당된 정수값을 표시
protected void onResume() {
super.onResume();
running = true;
}
Thread thread1 = new BackgroundThread();
thread1.start();
2. 새로 정의된 스레드 시작
표준자바에서 스레드 사용방법
protected void onPause() {
super.onPause();
3. 스레드 중지
running = false;
value = 0;
}
class BackgroundThread extends Thread {
public void run() {
while(running) {
try {
Thread.sleep(1000);
value++;
 버튼을 누르면 Value 변수에 들어
있는 정수 타입의 값을 텍스트 뷰
에 보여줌
 Value변수의 값은 스레드에 의해
1초마다 1씩 증가하며, 이러한 기
능을 수행하는 스레드를
Background Thread 라는 이름으
로 정의함
5. 1초마다 value값 증가
} catch(InterruptedException ex) {
Log.e("SampleJavaThread", "Exception
in thread.", ex);
}
}
}
}
4. 새로운 스레드 정의
<실행화면>
▶Hello world 버튼을 누르면 숫자가 나타나고 누를 때마다 1초에 1씩 증가됨.
III. 메시지 전송하여 실행하기
메시지 전송하여 실행하기
 메인 스레드
애플리케이션 객체인 액티비티, 브로트캐스트 수신자 등과 새로 만들어지는
윈도우를 관리하기 위한 메시지 큐(Message Queue)를 설명함
 메시지 큐 : Message Queue
순차적으로 코드를 수행함
 핸들러 : Handler
메시지 큐를 이용해 메인스레드에서 처리할 메시지를 전달하는 역할을 담당함.
특정 메시지가 미래의 어떤 시점에 실행되도록 스케줄링 할 수 있음
메시지 전송하여 실행하는 구조
메인스레드
<핸들러를 사용할 때 필요한 세가지 단계>
핸들러
(Handler)
(
3.Handl
e
massag
e
애플리케이션
구성요소들
1.Obtain Message
스레드#1
(Thread-1)
2.Send Message
 obtainMassage() - 호출의 결과로 메시지 객체를 리턴 받게 함
 sendMessage() - 메세지큐에 넣음
 handlerMassage() - 핸들메시지메소드에 정의된 기능이 수행됨
- 코드가 수행되는 위치는 새로 만든 스레드가 아닌 메인 스레드가 됨
메시지 전송하여 실행하는 구조
public class MainActivity extends Activity {
…
ProgressHandler handler;
…
1. 새로 정의한 핸들러 변수 선언
public void onCreate(Bundle savedInstanceState) {
handler = new ProgressHandler();
}
2. 액티비티가 만들어 질 때
핸들러 객체 생성
 핸들러 클래스를 상속한 ProgressHandler 새로 정의

Handle 클래스에 들어 있는 Handle Massage()메소드를 다시 정의하여 메시지가
메인 스레드에서 수행 될때 필요한 기능을 정의하기 위함
 정의한 핸들러는 onCreate()메소드에서 액티비티가 초기화 될때 new 연산자를
이용해 객체로 만들어짐
메시지 전송하여 실행하는 구조
public void onStart() {
…
Thread thread1 = new Thread(new
Runnable() {
public void run() {
3. 액티비티가 시작될 때 스레드를
만들어서 시작
…
Message msg = handler.obtainMessage();
handler.sendMessage(msg);
...
});
thread1.start();
}
4. 작업상태나 결과를 핸들러의
sendMessage()메소드로 전송
 New연산자를 이용하여 객체로 만든
후 start()메소드를 이용해 실행함
 스레드의 run()메소드 안에있는 코드
가 스레드 시작시에 수행됨
메시지 전송하여 실행하는 구조
public class ProgressHandler extends
Handler {
5. 핸들러클래스를 상속하여
새로운핸들러 클래스를 정의
public void handleMessage(Message msg){
…
}
}
}
6. 메소드 안에서 전달된
정보를이용해 UI 업데이트
 Run() 메소드 안에서는 별도의 스레드에서 수행한 작업의 결과가 나왔을때 핸
들러 객체인 obtainMessage()로 메시지 객체 하나를 참조한 후
sendMassage() 메소드를 이용해 메시지 큐에 넣음
메시지 전송하여 실행하는 구조
public class MainActivity extends Activity {
ProgressBar bar;
TextView textView01;
boolean isRunning = false;
ProgressHandler handler;
public void onCreate(Bundle
savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bar = (ProgressBar)
findViewById(R.id.progress);
textView01 = (TextView)
findViewById(R.id.textView01);
handler = new ProgressHandler();
}
 다른 액티비티의 자바코드이며
XML레이아웃에 정의된 프로그레스
바와 텍스트뷰에 진행상태를 나타낸
다.
 새로 만들어진 스레드에서 20회에 걸
쳐 메시지 객체를 전송 함으로써 메
시지가 처리할 때 마다 진행상태를
5%씩 증가 시킨다.
1. 새로정의한
ProgressH andler()객체 생성
public void onStart() {
super.onStart();
메시지 전송하여 실행하는 구조
public void onStart() {
super.onStart();
bar.setProgress(0);
Thread thread1 = new Thread(new
Runnable() {
public void run() {
try {
for (int i = 0; i < 20 && isRunning; i++) {
Thread.sleep(1000);
Message msg = handler.obtainMessage();
handler.sendMessage(msg);
}
} catch (Exception ex) {
Log.e("SampleThreadActivity",
"Exception in processing message.", ex);
}
}
});
}
isRunning = true;
thread1.start();
 프로그레스 바는 최대값이 100으로
정의 되어 있으므로 5%씩 값을 증가
시키기 위해서는
increamProgressBy()메소드를 이용
해 매번 5를 전달한다.
3. 스레드에서 1초마다
핸들러로 메시지 전송
2. 액티비티가 실행될 때
프로그레스 값을 0으로 실행
메시지 전송하여 실행하는 구조
isRunning = true;
thread1.start();
}
public void onStop() {
super.onStop();
}
isRunning = false;
public class ProgressHandler extends Handler {
public void handleMessage(Message msg) {
bar.incrementProgressBy(5);
if (bar.getProgress() == bar.getMax()) {
textView01.setText("Done");
} else {
textView01.setText("Working ..." +
bar.getProgress());
}
}
}
 텍스트 뷰에 현재 진행률 수치를
표시하기 위해 설정된 값을
getProgress()메소드를 이용해
가져온다.
4. Handler클래스를 상속하
여
새로운 핸들러 정의
5. 프로그레스 바의 값
업데이트
메시지 전송하여 실행하는 레이아웃
<LinearLayout
xmlns:android="http://schemas.android.com
/apk/res/android"
xmlns:tools="http://schemas.android.com/to
ols" android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#ffbbbbff" >
<TextView android:id="@+id/textView01"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="Working ..."
android:textSize="20dp"
android:textStyle="bold"
android:textColor="#ff000000" />
2. 진행상태를 표시하기 위한
프로그레스 바 정의
프로그레스 바는 원형이 막대 모양으
로 보여주기 위해 style속성
을 ?android:attr/progressBarStyle
Horizontal" 로 정의
1. 진행상태를 표시하기 위한
텍스트뷰 정의
<ProgressBar
android:id="@+id/progress"
style="?android:attr/progressBarStyl
eHorizontal"
android:layout_width="match_paren
t"
android:layout_height="wrap_conte
nt" android:max="100"
/>
</LinearLayout>
<실행화면>
▶진행률이 100%가 되면 텍스트 뷰에는 ‘Done’이라는 메시지만 남고 프
로그레스바는 다 채워진 상태로 멈추게 된다.
IV. Runnable객체 실행하기
Runnable객체 실행하기
 핸들러 클래스
메시지 전송 방법 이외에 Runnable 객체를 실행 시킬 수 있는 방법
을 제공함
 Runnable 객체
새로 만든 Runnable 객체를 핸들러의 post()메소드를 이용해 전달해
주기만 하면 이 객체에 정의된 run() 메소트 내의 코드들은 메인 스레
드 에서 실행됨
Runnable객체 실행하기-메인 액티비티 코
드
public class SampleThreadRunnableActivity extends
Activity {
…
Handler handler;
 일반적으로 사용하는 Handler
클래스를 이용하여 객체를 생성함
1. 핸들러의 변수선
언
ProgressRunnable runnable;
2. 새로 정의한 Runnable객체의 변수 선
언
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bar = (ProgressBar) findViewById(R.id.progress);
textView01 = (TextView)
findViewById(R.id.textView01);
}
handler = new Handler();
runnable = new ProgressRunnable();
public void onStart() {
3. 새로 정의한 Runnable객체의 변수 선
언
Runnable객체 실행하기-메인 액티비티 코드
public void onStart() {
Thread thread1 = new Thread(new
Runnable() {
public void run() {
try {
for (int i = 0; i < 20 && isRunning;
i++) {
Thread.sleep(1000);
handler.post(runnable);
}
} catch (Exception ex) {
Log.e("SampleThreadActivity",
"Exception in processing message.", ex);
}
}
});
isRunning = true;
thread1.start();
}
6. 새로 정의한 Runnable객체의
변수 선언
ProgressRunnable 클래스는 Runnable클래스
를 상속하여 정의하였으며 run()메소드 안에는
이전 예제에서 사용했던 handlerMassage()메
소드 안의 코드를 그대로 넣어 동일한 기능을
수행한다.
4. 핸들러의 변수선
언
5. 새로 정의한 Runnable객체의
변수 선언
public class ProgressRunnable implements
Runnable {
public void run() {
bar.incrementProgressBy(5);
if (bar.getProgress() ==
bar.getMax()) {
textView01.setText("Runnable
Runnable객체 실행하기-메인 액티비티 코드
public class SampleThreadRunnableActivity extends
Activity {
…
Handler handler;
ProgressRunnable runnable;
1. 핸들러의 변수선
언
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bar = (ProgressBar) findViewById(R.id.progress);
textView01 = (TextView)
findViewById(R.id.textView01);
}
handler = new Handler();
runnable = new ProgressRunnable();
public void onStart() {
 이전 예제에서 핸들러의 메시지
정송 방식을 사용했을 때의 코드
와 거의 동일하고 핸들러를 사용
하는 방식만 바뀜
2. 새로 정의한 Runnable객체의
변수 선언
Runnable객체 실행하기-메인 액티비티 코드
bar.setProgress(0);
3. 프로그레스 바를 0으로 설정하고 스레드시작
Thread thread1 = new Thread(new
Runnable() {
public void run() {
try {
for (int i = 0; i < 20 &&
isRunning; i++) {
Thread.sleep(1000);
handler.post(runnable);
4. 새로 생성한 Runnable 객체 전달
}
} catch (Exception ex) {
Log.e("SampleThreadActivity",
"Exception in processing message.", ex);
새로 만들어진 스레드 안에서 핸들
}
러 객체에 정의된 post()메소드를
}
호출하면서 Runnable객체를 전달하
});
isRunning = true;
thread1.start();
면 그 안에 정의된 run()메소드 내의
코드가 메인 스레드에서 실행되면서
프로그레스 바의 값을 바꿔주는 구
조이다.
Runnable객체 실행하기-메인 액티비티 코드
public void onStop() {
super.onStop();
}
isRunning = false;
public class ProgressRunnable implements
Runnable {
public void run() {
5. 프로그레스 바를 0으로 설정하고
스레드 시작
bar.incrementProgressBy(5);
if (bar.getProgress() == bar.getMax()) {
textView01.setText("Runnable Done");
} else {
textView01.setText("Runnable Working ..." +
bar.getProgress());
}
}
}
}
6. 새로 생성한 Runnable 객체 전
달
프로그레스 바의 값이 최대값에 도달
하게 되면 택스트 뷰에 표시되는 메시
지를 “Runnable Done”라고 표시하여
더 이상 스레드가 실행되지 않는 상태
를 것을 알 수 있도록 한다.