Android 비동기 메시지 메커니즘 상세 설명
그 중에서 Message 는 라인 간 에 전 달 된 메시지 로 what,arg 1,arg 2 필드 는 정형 데 이 터 를 휴대 할 수 있 고 obj 필드 는 Object 대상 을 휴대 할 수 있다.
Handler 는 메 시 지 를 보 내 고 처리 하 는 데 주로 사용 되 는 처리 자 입 니 다.메 시 지 를 보 내 는 방법 은 sendmessage 입 니 다.메 시 지 를 처리 하 는 방법 은 handleMessage()이 며,Message 필드 에 지 니 고 있 는 정 보 는 이 방법 에서 판별 합 니 다.
Message Queue 는 모든 Handler 가 보 낸 메 시 지 를 저장 하 는 메시지 큐 입 니 다.
Looper 는 메시지 큐 의'관리자'로 메시지 큐 에서 메 시 지 를 하나씩 꺼 내 Handler 의 handle Message()방법 에 할당 합 니 다.
비동기 메시지 처리 프로 세 스:
① 우선 메 인 스 레 드 에 Handler 대상 을 만 들 고 handleMessage()방법 을 다시 써 야 한다.
② 하위 스 레 드 가 처리 되 는 데 걸 리 는 시간 이 걸 릴 때 처리 결 과 를 UI 에 피드백 해 야 할 때 message 대상 을 만 들 고 what 필드 에 int 값 을 가지 고 Handler 대상 을 통 해 보 냅 니 다.
③ 이후 이 메 시 지 는 Message Queue 에 추가 되 어 처 리 를 기다 리 고 있 으 며,Looper 는 Message Queue 에서 처리 할 메 시 지 를 꺼 내 서 Handler 대상 의 handle Message()방법 으로 보 내 려 고 시도 하고 있다.Handler 대상 은 메 인 스 레 드 에서 만 들 어 졌 기 때문에 handleMessage()방법 에서 안심 하고 UI 작업 을 할 수 있 습 니 다.
하나의 예 를 통 해 확인 해 보 겠 습 니 다.이벤트 MainActivity 에는 단추 와 TextView 가 있 습 니 다.TextView 는"Hello World!"를 초기 화 합 니 다.이후 버튼 을 눌 러 시간 소모 조작 하기;시간 소모 작업 이 끝나 면 TextView 에'Nice to meet you'가 표 시 됩 니 다.이상 의 분석 에 근거 하여 나 는 비 할 바 없 이 자 연 스 럽 게 다음 과 같은 코드 를 썼 다.
package com.shaking.androidthreadtest;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private static final int UPDATE_TEXT=1;
private String data;
private TextView textView;
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case UPDATE_TEXT:
textView.setText(data);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
Button button=findViewById(R.id.button);
textView=findViewById(R.id.text_view);
button.setOnClickListener(this);
}
@Override
public void onClick(View view) {
new Thread(new Runnable() {
@Override
public void run() {
// , data
data="Nice to meet you";
Message message=new Message();
message.what=UPDATE_TEXT;
handler.sendMessage(message);
}
}).start();
}
}
우선,이렇게 쓰 는 것 은 틀림없이 잘못 이 없 을 것 이다!프로그램 도 정상적으로 작 동 할 수 있다.그러나 IDE 는"This Handler class should be static or leaks might occur"라 고 경고 했다.이 경 고 는 우리 가 Handler 라 는 종 류 를 사용 할 때 정적 으로 밝 혀 야 한 다 는 뜻 이다.그렇지 않 으 면 메모리 가 새 어 나 갈 수 있다.
그렇다면 왜 메모리 유출 이 일 어 났 을 까?원인 은:
첫째:Handler 대상 의 sendmessage()방법 으로 Message 대상 을 보 낼 때 이 Message 대상 은 이 Handler 대상 에 대한 인용 을 가지 고 있 습 니 다(바로 이 인용 에 의 해 Looper 가 메시지 대기 열 에서 이 Message 대상 을 꺼 낸 후에 야 이 Message 대상 을 정확하게 이 Handler 대상 으로 나 눌 수 있 습 니 다!).
둘째,주 스 레 드 에서 Handler 대상 을 만 들 때 handleMessage()방법 을 다시 쓰기 위해 익명 내부 클래스 를 사용 하여 Handler 대상 을 만 들 었 습 니 다.익명 내부 클래스 와 비정 상 내부 클래스 는 모두 외부 클래스 에 대한 인용 을 은연 중 에 가지 고 있 습 니 다!따라서 이 Handler 대상 은 외부 클래스 인 MainActivity 의 인용 을 가지 고 있다.
상기 두 가 지 를 결합 하면 문제 가 생 긴 다.Message 대상 은 Handler 대상 인용 을 가지 고 있 고 Handler 대상 은 MainActivity 의 인용 을 가지 고 있다.그래서 MainActivity 이 활동 은 메시지 가 회수 될 때 까지 메모리 에서 회수 할 수 없습니다!Message 대상 이 하위 스 레 드 에서 메시지 대기 열 로 전송 되 고 처리 되 지 않 으 면 메모리 에서 회수 되 지 않 고 메 인 스 레 드 가 계속 걸 려 있 습 니 다.그래서 메모리 유출 로 이 어 질 수 있다.
이 유 를 알 았 다 면 해결 방법 은 무엇 입 니까?사실 이전의 경 고 는 이미 해결 방안 을 제시 했다.정적 내부 클래스 를 통 해 Handler 대상 을 만 드 는 것 입 니 다.정적 내부 클래스 는 외부 클래스 의 인용 을 가지 지 않 기 때 문 입 니 다.
이때,나 는 자 연 스 럽 게 정적 내부 클래스 를 만 들 고 Handler 클래스 를 계승 한 다음 에 handleMessage 방법 을 다시 쓴다.
private static class MyHandler extends Handler{
@Override
public void handleMessage(Message msg) {
}
}
그런데 여기 또 문제 가 생 겼 어 요!만약 내 가 외부 류 에 대한 인용 을 가지 고 있 지 않다 면,나 는 어떻게 외부 류 의 방법 과 대상 을 사용 합 니까?handle Message()방법 에서 UI 작업 을 해 야 하 니까 요.정적 내부 클래스 를 사용 하여 메모리 유출 을 피하 고 외부 클래스 를 호출 하 는 방법 이 필요 한 경우:약 한 인용 을 사용 할 수 있 습 니 다!즉,우 리 는 이 내부 류 에서 대외 부 대상 의 약 한 인용 을 성명 하 는 것 이다.이렇게 하면 외부 클래스 를 호출 할 수 있 고 메모리 유출 을 초래 하지 않 을 것 이다.
구체 적 으로 수 정 된 코드 는 다음 과 같다.
package com.shaking.androidthreadtest;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.lang.ref.WeakReference;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private static final int UPDATE_TEXT=1;
private String data;
private TextView textView;
private static class MyHandler extends Handler{
//
private WeakReference<MainActivity> weakReference;
//
MyHandler(MainActivity activity){
weakReference=new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
// get()
MainActivity activity=weakReference.get();
activity.textView.setText(activity.data);
}
}
// Handler
private MyHandler handler=new MyHandler(this);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
Button button=findViewById(R.id.button);
textView=findViewById(R.id.text_view);
button.setOnClickListener(this);
}
@Override
public void onClick(View view) {
new Thread(new Runnable() {
@Override
public void run() {
// , data
data="Nice to meet you";
Message message=new Message();
message.what=UPDATE_TEXT;
handler.sendMessage(message);
}
}).start();
}
}
이상 의 모든 문 제 를 완벽 하 게 해결 하 세 요!6~마지막 으로 마지막 해결 방안 을 직접 사용 하 는 것 을 추천 합 니 다:정적 내부 클래스+약 참조.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 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에 따라 라이센스가 부여됩니다.