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”라고 표시하여
더 이상 스레드가 실행되지 않는 상태
를 것을 알 수 있도록 한다.