Android:Handler
术语
Looper
每一个线程只有一个Looper,每个线程在初始化Looper之后,然后Looper会维护好该线程的消息队列,用来存放Handler发送的Message,并处理消息队列出队的Message。它的特点是它跟它的线程是绑定的,处理消息也是在Looper所在的线程去处理,所以当我们在主线程创建Handler时,它就会跟主线程唯一的Looper绑定,从而我们使用Handler在子线程发消息时,最终也是在主线程处理,达到了异步的效果。
在主线程中,ActivityThread默认会把Looper初始化好,prepare以后,当前线程就会变成一个Looper线程。
MessageQueue
MessageQueue是一个消息队列,用来存放Handler发送的消息。每个线程最多只有一个MessageQueue。MessageQueue通常都是由Looper来管理,而主线程创建时,会创建一个默认的Looper对象,而Looper对象的创建,将自动创建一个MessageQueue。其他非主线程,不会自动创建Looper。
Message
消息对象,就是MessageQueue里面存放的对象,一个MessageQueu可以包括多个Message。当我们需要发送一个Message时,我们一般不建议使用new Message()的形式来创建,更推荐使用Message.obtain()来获取Message实例,因为在Message类里面定义了一个消息池,当消息池里存在未使用的消息时,便返回,如果没有未使用的消息,则通过new的方式创建返回,所以使用Message.obtain()的方式来获取实例可以大大减少当有大量Message对象而产生的垃圾回收问题。
示例:
HandlerActivity
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
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 com.tencent.testand.R;
import java.lang.ref.WeakReference;
public class HandlerActivity extends AppCompatActivity implements View.OnClickListener {
private Button mSendMsgButton;
private TextView mShowMsgTextView;
private MessageHandler mMessageHandler = new MessageHandler(this);
private static final int MESSAGE_CODE = 999999;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
mSendMsgButton = findViewById(R.id.send_message_btn);
mSendMsgButton.setOnClickListener(this);
mShowMsgTextView = findViewById(R.id.show_msg_tv);
// 获取包信息
getAppInfo();
}
@Override
protected void onDestroy() {
super.onDestroy();
// 销毁handler
mMessageHandler.removeCallbacksAndMessages(null);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.send_message_btn: {
startCountdown();
break;
}
}
}
/**
* 获取App信息
*/
private void getAppInfo() {
try {
PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
mShowMsgTextView.setText(packageInfo.packageName + packageInfo.versionName);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
/**
* 倒计时
*/
private void startCountdown() {
Message msg = mMessageHandler.obtainMessage();
msg.obj = 20000;
msg.what = MESSAGE_CODE;
mMessageHandler.sendMessageDelayed(msg, 1000);
}
// Getter
public TextView getShowMsgTextView() {
return mShowMsgTextView;
}
/**
* 内部类
*/
public static class MessageHandler extends Handler {
public final WeakReference<HandlerActivity> mActivityWeakReference;
public MessageHandler(HandlerActivity activity) {
mActivityWeakReference = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
HandlerActivity handlerActivity = mActivityWeakReference.get();
switch (msg.what) {
case MESSAGE_CODE: {
int value = (int) msg.obj;
handlerActivity.getShowMsgTextView().setText(String.valueOf(value/1000));
msg = Message.obtain();
msg.what = MESSAGE_CODE;
msg.obj = value - 1000;
if (value > 0) {
sendMessageDelayed(msg, 1000);
}
}
}
}
}
}
注:由于布局只是一个简单的TextView,这里不再给出代码。