应用场景
Handler是一种异步消息传递机制,最基本的应用场景就是更新UI。其他的应用实例场景
- 传递消息更新UI
- 倒计时的View的实现
- 结合IntentService的使用
传递消息更新UI
代码转载自:https://www.jianshu.com/p/e172a2d58905
java
/**
* 方式1:新建Handler子类(内部类)
*/
// 步骤1:自定义Handler子类(继承Handler类) & 复写handleMessage()方法
class mHandler extends Handler {
// 通过复写handlerMessage() 从而确定更新UI的操作
@Override
public void handleMessage(Message msg) {
...// 需执行的UI操作
}
}
// 步骤2:在主线程中创建Handler实例
private Handler mhandler = new mHandler();
// 步骤3:创建所需的消息对象
Message msg = Message.obtain(); // 实例化消息对象
msg.what = 1; // 消息标识
msg.obj = "AA"; // 消息内容存放
// 步骤4:在工作线程中 通过Handler发送消息到消息队列中
// 可通过sendMessage() / post()
// 多线程可采用AsyncTask、继承Thread类、实现Runnable
mHandler.sendMessage(msg);
// 步骤5:开启工作线程(同时启动了Handler)
// 多线程可采用AsyncTask、继承Thread类、实现Runnable
/**
* 方式2:匿名内部类
*/
// 步骤1:在主线程中 通过匿名内部类 创建Handler类对象
private Handler mhandler = new Handler(){
// 通过复写handlerMessage()从而确定更新UI的操作
@Override
public void handleMessage(Message msg) {
...// 需执行的UI操作
}
};
// 步骤2:创建消息对象
Message msg = Message.obtain(); // 实例化消息对象
msg.what = 1; // 消息标识
msg.obj = "AA"; // 消息内容存放
// 步骤3:在工作线程中 通过Handler发送消息到消息队列中
// 多线程可采用AsyncTask、继承Thread类、实现Runnable
mHandler.sendMessage(msg);
// 步骤4:开启工作线程(同时启动了Handler)
// 多线程可采用AsyncTask、继承Thread类、实现Runnable
具体的应用实例
java
public class MainActivity extends AppCompatActivity {
public TextView mTextView;
public Handler mHandler;
// 步骤1:(自定义)新创建Handler子类(继承Handler类) & 复写handleMessage()方法
class Mhandler extends Handler {
// 通过复写handlerMessage() 从而确定更新UI的操作
@Override
public void handleMessage(Message msg) {
// 根据不同线程发送过来的消息,执行不同的UI操作
// 根据 Message对象的what属性 标识不同的消息
switch (msg.what) {
case 1:
mTextView.setText("执行了线程1的UI操作");
break;
case 2:
mTextView.setText("执行了线程2的UI操作");
break;
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.show);
// 步骤2:在主线程中创建Handler实例
mHandler = new Mhandler();
// 采用继承Thread类实现多线程演示
new Thread() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 步骤3:创建所需的消息对象
Message msg = Message.obtain();
msg.what = 1; // 消息标识
msg.obj = "A"; // 消息内存存放
// 步骤4:在工作线程中 通过Handler发送消息到消息队列中
mHandler.sendMessage(msg);
}
}.start();
// 步骤5:开启工作线程(同时启动了Handler)
// 此处用2个工作线程展示
new Thread() {
@Override
public void run() {
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 通过sendMessage()发送
// a. 定义要发送的消息
Message msg = Message.obtain();
msg.what = 2; //消息的标识
msg.obj = "B"; // 消息的存放
// b. 通过Handler发送消息到其绑定的消息队列
mHandler.sendMessage(msg);
}
}.start();
}
}
倒计时View的实现
倒计时的View其实挺常见的,比如我们在获取验证码的时候就需要设计一个倒计时的Button,用户点击后显示一个60s的倒计时,并且实时递减,更新在Button上,这就可以使用Handler实现。 代码转载自:https://www.jianshu.com/p/916bc0645295
java
public class CountDownView extends AppCompatTextView {
/**
* 总时间
*/
private long seconds;
/**
* 当前分钟
*/
private long minutes;
/**
* 当前秒数
*/
private int second = 60;
private static final int SECONDS_PER_MINUTE = 60;
private static final int MILLS_PER_SECOND = 1000;
private static final int MILLS_PER_MINUTE = SECONDS_PER_MINUTE * 1000;
private static final int WHAT_DONE = 2;
private static final int WHAT_TICK = 1;
private int marginEnd;
private StringBuilder content = new StringBuilder();
public CountDownView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
DeviceProfile deviceProfile = Launcher.getLauncher(getContext()).getDeviceProfile();
int size = (int) (MeasureSpec.getSize(widthMeasureSpec) / deviceProfile.inv.numColumns);
marginEnd = marginEnd == 0 ? (size - deviceProfile.iconSizePx) / 2 : marginEnd;
setMarginEnd(marginEnd);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private void setMarginEnd(int marginEnd) {
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams();
layoutParams.setMarginEnd(marginEnd);
layoutParams.resolveLayoutDirection(layoutParams.getLayoutDirection());
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (handler.hasMessages(WHAT_TICK)) {
handler.removeMessages(WHAT_TICK);
}
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case WHAT_DONE:
setVisibility(View.GONE);
break;
default:
setText(content.toString());
handler.post(runnable);
break;
}
}
};
/***
* 设置倒计时
* @param millis
*/
public void setCountDownMills(long millis) {
seconds = (long) Math.floor(millis / MILLS_PER_SECOND);
minutes = (long) Math.floor(millis / MILLS_PER_MINUTE) - 1;
// start after one second
handler.postDelayed(runnable, MILLS_PER_SECOND);
}
private Runnable runnable = new Runnable() {
@Override
public void run() {
if (seconds <= 0) {
handler.sendEmptyMessage(WHAT_DONE);
return;
}
seconds--;
if (second <= 0) {
second = SECONDS_PER_MINUTE;
minutes = (long) Math.floor(seconds / SECONDS_PER_MINUTE);
}
second--;
content.delete(0, content.length());
appendZeroWhenLower10(minutes);
content.append(":");
appendZeroWhenLower10(second);
if (handler.hasMessages(WHAT_TICK)) {
handler.removeMessages(WHAT_TICK);
}
handler.sendEmptyMessageDelayed(WHAT_TICK, MILLS_PER_SECOND);
}
};
private StringBuilder appendZeroWhenLower10(long value) {
if (value < 10) {
content.append("0").append(value);
} else {
content.append(value);
}
return content;
}
}