Android Handler 다 중 스 레 드 상세 설명
머리말
Android 의 메시지 전달 메커니즘 은 또 다른 형식의'이벤트 처리'입 니 다.이 메커니즘 은 주로 Android 응용 프로그램의 다 중 스 레 드 문 제 를 해결 하기 위해 서 입 니 다.Android 에 서 는 Activity 가 새로 시작 하 는 스 레 드 가 이 Activity 의 UI 구성 요소 에 접근 하 는 것 을 허용 하지 않 습 니 다.그러면 새로 시작 하 는 스 레 드 가 UI 구성 요소 의 속성 값 을 변경 할 수 없습니다.그러나 실제 개발 에서 많은 부분 에서 작업 라인 에서 UI 구성 요소 의 속성 값 을 바 꿔 야 한다.예 를 들 어 네트워크 이미지 다운로드,애니메이션 다운로드 등 이다.이 블 로 그 는 주로 Handler 가 스 레 드 에 올 라 온 메 시 지 를 어떻게 보 내 고 처리 하 는 지 를 소개 하고 Message 의 몇 가지 데 이 터 를 전달 하 는 방식 을 설명 하 며 마지막 으로 모두 작은 데모 로 시연 한다.
Handler
Handler 는 Object 에서 직접 계승 합 니 다.Handler 는 Message 나 Runnable 대상 을 보 내 고 처리 할 수 있 으 며 메 인 스 레 드 의 Message Queue 에 연 결 됩 니 다.각각 Handler 는 하나의 단독 스 레 드 를 가지 고 있 으 며 하나의 메시지 큐 에 연 결 된 스 레 드 를 가지 고 있 습 니 다.즉,Handler 는 고유 한 메시지 큐 를 가지 고 있 습 니 다.Handler 를 예화 할 때 하나의 스 레 드 와 메시지 큐 의 스 레 드 에 실 을 수 있 습 니 다.이 Handler 는 Message 나 Runnable 을 메시지 큐 에 누 르 고 메시지 큐 에서 Message 나 Runnable 을 꺼 내 서 조작 할 수 있 습 니 다.
Handler 는 주로 두 가지 역할 을 합 니 다.
작업 스 레 드 에서 메 시 지 를 보 냅 니 다.
UI 스 레 드 에서 정 보 를 가 져 오고 처리 합 니 다.
Handler 는 메시지 대상 이나 Runnable 대상 을 메시지 대기 열 에 눌 러 서 UI 스 레 드 에서 Message 를 가 져 오 거나 Runnable 대상 을 실행 할 수 있 기 때문에 Handler 는 메시지 대기 열 에 눌 러 두 가지 시스템 이 있 습 니 다.Post 와 sendmessage:
Post:Post 는 Runnable 대상 을 메시지 대기 열 에 넣 을 수 있 도록 합 니 다.그것 의 방법 은 post(Runnable),postAtTime(Runnable,long),postDelayed(Runnable,long)가 있다.
sendmessage:sendmessage 는 메시지 데 이 터 를 포함 하 는 Message 대상 을 메시지 대기 열 에 누 를 수 있 습 니 다.이 방법 은 sendEmpty Message(int),sendmessage(Message),sendmessage AtTime(Message,long),sendmessage Delayed(Message,long)가 있 습 니 다.
위의 여러 가지 방법 을 통 해 알 수 있 듯 이 post 든 sendmessage 든 모두 여러 가지 방법 을 가지 고 있 습 니 다.Runnable 대상 과 Message 대상 이 메시지 대기 열 에 들 어가 면 즉시 실행 하거나 지연 시 킬 수 있 습 니 다.
Post
Handler 의 Post 방식 에 있어 서 Runnable 대상 을 메시지 대기 열 에 전달 합 니 다.이 Runnable 대상 에서 run()방법 을 다시 씁 니 다.일반적으로 이 run()방법 에 UI 스 레 드 에 필요 한 동작 을 기록 합 니 다.
Handler 에서 Post 방식 에 대한 방법 은 다음 과 같 습 니 다.
boolean post(Runnable r):Runnable 하 나 를 메시지 대기 열 에 넣 고 UI 스 레 드 를 메시지 대기 열 에서 이 대상 을 꺼 낸 후 즉시 실행 합 니 다.
boolean postAtTime(Runnable r,long uptime Millis):Runnable 을 메시지 대기 열 에 넣 고 UI 스 레 드 를 메시지 대기 열 에서 이 대상 을 꺼 낸 후 특정한 시간 에 실행 합 니 다.
boolean postDelayed(Runnable r,long delay Millis):Runnable 하 나 를 메시지 대기 열 에 넣 고 UI 스 레 드 를 메시지 대기 열 에서 이 대상 을 꺼 낸 후 delay Mills 초 지연 실행
void removeCallbacks(Runnable r):메시지 대기 열 에서 Runnable 대상 을 제거 합 니 다.
다음은 Demo 를 통 해 Handler 의 post 방식 으로 새로 시작 하 는 스 레 드 에서 UI 구성 요소 의 속성 을 수정 하 는 방법 을 설명 합 니 다.
package com.bgxt.datatimepickerdemo;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class HandlerPostActivity1 extends Activity {
private Button btnMes1,btnMes2;
private TextView tvMessage;
// Handler
private static Handler handler=new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.message_activity);
btnMes1=(Button)findViewById(R.id.btnMes1);
btnMes2=(Button)findViewById(R.id.btnMes2);
tvMessage=(TextView)findViewById(R.id.tvMessage);
btnMes1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//
new Thread(new Runnable() {
@Override
public void run() {
// tvMessage.setText("...");
// , UI ,UI UI
// post UI tvMessage Text
handler.post(new Runnable() {
@Override
public void run() {
tvMessage.setText(" Handler.post , 。");
}
});
}
}).start();
}
});
btnMes2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
// postDelayed UI tvMessage Text
// 3S
handler.postDelayed(new Runnable() {
@Override
public void run() {
tvMessage.setText(" Handler.postDelayed , 3S 。");
}
}, 3000);
}
}).start();
}
});
}
}
효과 표시:한 가지 주의해 야 할 것 은 Post 방식 에 있어 서 Runnable 대상 의 run()방법 코드 는 모두 UI 스 레 드 에서 실 행 됩 니 다.따라서 이 코드 에 있어 서 UI 스 레 드 에서 의 작업 을 수행 할 수 없고 post 방식 으로 실 행 될 수 없습니다.예 를 들 어 네트워크 를 방문 하면 다음 과 같은 예 를 들 어 post 방식 으로 인터넷 에서 그림 을 가 져 옵 니 다.이미지 뷰 에 표 시 됩 니 다.
package com.bgxt.datatimepickerdemo;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
public class HandlerPostActivity2 extends Activity {
private Button btnDown;
private ImageView ivImage;
private static String image_path = "http://ww4.sinaimg.cn/bmiddle/786013a5jw1e7akotp4bcj20c80i3aao.jpg";
private ProgressDialog dialog;
// Handler,Handler
private static Handler handler=new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.asynctask_activity);
btnDown = (Button) findViewById(R.id.btnDown);
ivImage = (ImageView) findViewById(R.id.ivSinaImage);
dialog = new ProgressDialog(this);
dialog.setTitle(" ");
dialog.setMessage(" , ...");
dialog.setCancelable(false);
btnDown.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// ,
new Thread(new MyThread()).start();
//
dialog.show();
}
});
}
public class MyThread implements Runnable {
@Override
public void run() {
//
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(image_path);
HttpResponse httpResponse = null;
try {
httpResponse = httpClient.execute(httpGet);
if (httpResponse.getStatusLine().getStatusCode() == 200) {
byte[] data = EntityUtils.toByteArray(httpResponse
.getEntity());
// Bitmap , post , final
final Bitmap bmp=BitmapFactory.decodeByteArray(data, 0, data.length);
handler.post(new Runnable() {
@Override
public void run() {
// Post UI ImageView
ivImage.setImageBitmap(bmp);
}
});
//
dialog.dismiss();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
효과 표시:Message
Handler 가 sendmessage 방식 으로 메 시 지 를 메시지 큐 에 넣 으 려 면 Message 대상 을 전달 해 야 하 며,Handler 에 서 는 작업 스 레 드 에서 전 달 된 메 시 지 를 가 져 오 는 데 사용 할 handle Message()방법 을 다시 써 야 합 니 다.이 방법 은 UI 스 레 드 에서 실 행 됩 니 다.다음은 Message 를 소개 하 겠 습 니 다.
Message 는 final 클래스 이기 때문에 계승 할 수 없습니다.Message 는 스 레 드 에서 전 달 된 메 시 지 를 패키지 합 니 다.일반적인 데이터 에 대해 Message 는 getData()와 setData()방법 으로 데 이 터 를 가 져 오고 설정 합 니 다.그 중에서 작 동 하 는 데 이 터 는 Bundle 대상 입 니 다.이 Bundle 대상 은 일련의 getXxx()와 setXxx()방법 을 제공 하여 기본 데이터 형식의 키 쌍 을 전달 합 니 다.기본 데이터 형식 에 대해 서 는 간단 합 니 다.여 기 는 더 이상 상세 하 게 설명 하지 않 겠 습 니 다.한편,복잡 한 데이터 유형,예 를 들 어 한 대상 의 전달 은 상대 적 으로 복잡 해 야 한다.Bundle 에서 대상 을 전달 하 는 두 가지 방법 을 제 공 했 지만 이 두 가지 방법 도 해당 하 는 제한 이 있어 특정한 인 터 페 이 스 를 실현 해 야 한다.물론 일부 안 드 로 이 드 자체 의 유형 은 이 두 인터페이스 중의 하 나 를 실현 하여 직접 사용 할 수 있다.방법 은 다음 과 같다.
putParcelable(String key,Parcelable value):전달 해 야 할 대상 클래스 는 Parcelable 인 터 페 이 스 를 실현 합 니 다.
pubSerializable(String key,Serializable value):전달 해 야 할 대상 클래스 가 Serializable 인 터 페 이 스 를 실현 합 니 다.
또 다른 방식 으로 Message 에서 대상 을 전달 합 니 다.그것 은 Message 자체 가 가 진 obj 속성 전송 값 입 니 다.이것 은 Object 형식 이기 때문에 임의의 유형의 대상 을 전달 할 수 있 습 니 다.Message 자체 가 가 진 것 은 다음 과 같은 몇 가지 속성 이 있 습 니 다.
int arg 1:매개 변 수 는 복잡 하지 않 은 데 이 터 를 전달 하 는 데 사용 되 고 복잡 한 데 이 터 는 setData()로 전달 합 니 다.
int arg 2:매개 변수 2.복잡 하지 않 은 데 이 터 를 전달 하고 복잡 한 데 이 터 는 setData()로 전달 합 니 다.
Object obj:임의의 대상 을 전달 합 니 다.
int what:정 의 된 메시지 코드 는 일반적으로 메시지 의 표 지 를 설정 하 는 데 사 용 됩 니 다.
Message 대상 에 대해 서 는 구조 적 방법 을 직접 사용 하 는 것 을 추천 하지 않 고 Message.obtain()이라는 정적 방법 이나 Handler.obtainMessage()를 사용 하여 얻 는 것 을 권장 합 니 다.Message.obtain()은 메시지 풀 에서 Message 대상 을 가 져 옵 니 다.메시지 풀 이 비어 있어 야 구조 적 방법 으로 새로운 Message 를 예화 할 수 있 습 니 다.그러면 메시지 자원 의 이용 에 유리 합 니 다.메시지 탱크 에 소식 이 너무 많 을 까 봐 걱정 할 필 요 는 없다.상한 선 이 있 고 상한 선 은 10 개다.Handler.obtainMessage()는 여러 가지 리 로드 방법 을 가지 고 있 으 며,원본 코드 를 보면 실제로 Handler.obtainMessage()가 내부 에서 도 호출 된 Message.obtain()임 을 알 수 있다.
Message 가 온라인 으로 메 시 지 를 전달 하 는 것 이 므 로 먼저 하나의 데모 로 Message 의 사용 을 설명 하 시 겠 습 니까?아니면 일반적인 인터넷 에서 한 장의 그림 을 다운로드 하 는 Demo 입 니까?다운로드 한 후에 ImageView 컨트롤 로 보 여 줍 니 다.
package com.bgxt.datatimepickerdemo;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
public class HandlerMessageActivity1 extends Activity {
private Button btnDown;
private ImageView ivImage;
private static String image_path = "http://ww4.sinaimg.cn/bmiddle/786013a5jw1e7akotp4bcj20c80i3aao.jpg";
private ProgressDialog dialog;
private static int IS_FINISH = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.asynctask_activity);
btnDown = (Button) findViewById(R.id.btnDown);
ivImage = (ImageView) findViewById(R.id.ivSinaImage);
dialog = new ProgressDialog(this);
dialog.setTitle(" ");
dialog.setMessage(" , ...");
dialog.setCancelable(false);
btnDown.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new MyThread()).start();
dialog.show();
}
});
}
private Handler handler = new Handler() {
// Handler , handleMessage()
@Override
public void handleMessage(Message msg) {
// 1
if(msg.what==IS_FINISH){
byte[] data=(byte[])msg.obj;
Bitmap bmp=BitmapFactory.decodeByteArray(data, 0, data.length);
ivImage.setImageBitmap(bmp);
dialog.dismiss();
}
}
};
public class MyThread implements Runnable {
@Override
public void run() {
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(image_path);
HttpResponse httpResponse = null;
try {
httpResponse = httpClient.execute(httpGet);
if (httpResponse.getStatusLine().getStatusCode() == 200) {
byte[] data = EntityUtils.toByteArray(httpResponse
.getEntity());
// Message , what 1
Message msg = Message.obtain();
msg.obj = data;
msg.what = IS_FINISH;
//
handler.sendMessage(msg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
효과 보 여주 기:Message.obtain()방법 은 여러 가지 재 업로드 방법 을 가지 고 있 으 며,크게 두 가지 로 나 눌 수 있 습 니 다.하 나 는 Handler 대상 을 전달 하지 않 아 도 되 는 방법 입 니 다.이러한 방법 에 대해 서 는 메 시 지 를 채 우 면 Handler.sendmessage()방법 으로 메 시 지 를 보 내야 합 니 다.두 번 째 유형 은 Handler 대상 을 전달 해 야 합 니 다.이러한 방법 은 Message.sendToTarget()방법 으로 메시지 대기 열 에 메 시 지 를 보 낼 수 있 습 니 다.이것 은 Message 대상 에 개인 적 인 Handler 형식의 속성 Target 이 있 기 때 문 입 니 다.그 당시 obtain 방법 이 Handler 대상 에 전 달 될 때 Target 속성 에 값 을 부여 하고 sendToTarget()방법 을 호출 할 때실제 내부 에 서 는 Target.sendmessage()방법 을 호출 합 니 다.
Handler 에서 도 빈 메 시 지 를 보 내 는 방법 을 정의 했다.예 를 들 어 sendEmpty Message(int what),sendEmpty Message Delayed(int what,long delay Millis)는 이러한 방법 으로 Message 를 사용 하지 않 으 면 메 시 지 를 보 낼 수 있 는 것 처럼 보이 지만 소스 코드 를 보면 내부 도 Message.obtain()방법 에서 메시지 대상 을 얻 을 수 있다.그리고 속성 에 값 을 부여 하고 마지막 으로 sendmessage()를 사용 하여 메시지 대기 열 에 메 시 지 를 보 냅 니 다.
Handler 에서 Message 메 시 지 를 보 내 는 방법 은 다음 과 같 습 니 다.
Message obtainMessage():Message 대상 을 가 져 옵 니 다.
boolean sendmessage():메시지 대기 열 에 Message 대상 을 보 내 고 UI 스 레 드 에서 메 시 지 를 가 져 오 면 즉시 실행 합 니 다.
boolean sendmessage Delayed():메시지 대기 열 에 Message 대상 을 보 내 고 UI 스 레 드 에서 메 시 지 를 가 져 온 후 실행 을 지연 합 니 다.
boolean sendEmpty Message(int what):빈 Message 대상 을 대기 열 에 보 내 고 UI 스 레 드 에서 메 시 지 를 가 져 오 면 즉시 실행 합 니 다.
boolean sendEmpty MessageDelayed(int what,long delay Millis):메시지 대기 열 에 빈 Message 대상 을 보 내 고 UI 스 레 드 에서 메 시 지 를 가 져 온 후 실행 을 지연 합 니 다.
void removeMessage():메시지 대기 열 에서 응답 하지 않 은 메 시 지 를 제거 합 니 다.
다음은 작은 Demo 를 통 해 메 시 지 를 보 내 는 여러 가지 방법 을 보 여 드 리 겠 습 니 다.
package com.bgxt.datatimepickerdemo;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class HandlerMessageActivity2 extends Activity {
private Button btn1, btn2, btn3, btn4,btn5;
private static TextView tvMes;
private static Handler handler = new Handler() {
@Override
public void handleMessage(android.os.Message msg) {
if (msg.what == 3||msg.what==5) {
tvMes.setText("what=" + msg.what + ", ");
} else {
tvMes.setText("what=" + msg.what + "," + msg.obj.toString());
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.message_activity2);
tvMes = (TextView) findViewById(R.id.tvMes);
btn1 = (Button) findViewById(R.id.btnMessage1);
btn2 = (Button) findViewById(R.id.btnMessage2);
btn3 = (Button) findViewById(R.id.btnMessage3);
btn4 = (Button) findViewById(R.id.btnMessage4);
btn5 = (Button) findViewById(R.id.btnMessage5);
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Message.Obtain+Hander.sendMessage()
new Thread(new Runnable() {
@Override
public void run() {
Message msg = Message.obtain();
msg.what = 1;
msg.obj = " Message.Obtain+Hander.sendMessage() ";
handler.sendMessage(msg);
}
}).start();
}
});
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Message.sendToTarget
new Thread(new Runnable() {
@Override
public void run() {
Message msg = Message.obtain(handler);
msg.what = 2;
msg.obj = " Message.sendToTarget ";
msg.sendToTarget();
}
}).start();
}
});
btn3.setOnClickListener(new View.OnClickListener() {
//
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
handler.sendEmptyMessage(3);
}
}).start();
}
});
btn4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
Message msg = Message.obtain();
msg.what =4;
msg.obj = " Message.Obtain+Hander.sendMessage() ";
handler.sendMessageDelayed(msg, 3000);
}
}).start();
}
});
btn5.setOnClickListener(new View.OnClickListener() {
//
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
handler.sendEmptyMessageDelayed(5, 3000);
}
}).start();
}
});
}
}
효과 전시이상 은 안 드 로 이 드 핸들 러 에 대한 자 료 를 정리 하고 후속 적 으로 관련 자 료 를 계속 보충 하 는 것 입 니 다.본 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.