异步的消息回调机制,利用Handle来发送消息和处理消息(消息放于线程消息队列中)
应用场景一:android应用UI每隔10秒去请求web端接口,获取数据库message消息表中最新的“我的未读消息”记录数,并高亮显示在UI里
习惯了java编程,我们一开始会试图用下面的代码来刷新UI
new Thread( new Runnable() {
public void run() {
myView.invalidate();
}
}).start();
在android平台开发时这样是不行的,因为它违背了单线程模型 :Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。
一般借助Handle则可以实现这一效果
MessageThread thread=new MessageThread();
thread.isRunning=true;
thread.start();
TextView bg=(TextView)layout.findViewById(R.id.tv);
class MessageThread extends Thread{
public boolean isRunning = true;
@Override
public void run() {
while(isRunning){
try {
//getMsgcount();
count=dao.getMsgCount()+"";//往数据库获取未读消息数
Message m=new Message();//创建一个新的消息
m.what=1;
handler.sendMessage(m);//handler发送消息,参数m为1
Thread.sleep(10000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public Handler handler=new Handler(){
public void handleMessage(Message msg) {//handleMessage消息处理者执行处理方法
super.handleMessage(msg);
if(msg.what==1){
if(!"".equals(count)&&count!=null){
int msgcount=Integer.valueOf(count);
if(msgcount==0){
bd.hide();
}else{
bd.setText(msgcount+"");
bd.show(); }
}
}
}
};
既然无法在子线程中去更新UI,那我们可以借助handler消息处理机制。
其主要原理可以这样简单的理解:
1、创建一个子线程,由它借用主线程里的handler去发送一个消息给主线程handle.sendMessage(),这个消息会被主线程放入到消息队列里message queue,主线程里会有一个looper对这些消息进行轮询,并调用handler消息处理者,执行handleMessage方法,就可以在handleMessage方法里更新UI了。
应用场景二:handler.postDelayed,实现定时器或延时器。
welcome页面停留两秒后往左侧滑动,进入登录页面
public class WelcomeActivity extends FragmentActivity {
private Handler mHandler;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.welcome_main);
mHandler = new Handler();
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
Intent intent = new Intent();
intent.setClass(getApplicationContext(), LoginActivity.class);
startActivity(intent);
finish();
overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out);
}
}, 2000);
}
}
public void overridePendingTransition(int enterAnim, int exitAnim);实现两个Activity之间的动画切换,从一个activity跳转到另外一个activity时的动画。
enterAnim是第一个activity退出时的动画;
exitAnim是第二个activity进入时的动画;
push_left_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="100%p" android:toXDelta="0"
android:duration="500" />
</set>
push_left_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0" android:toXDelta="-100%p"
android:duration="500" />
</set>
这就实现了延时两秒滑动进入的延时器,如要该装成每个两秒循环执行的定时器,只需稍作改动。
mHandler = new Handler();
Runnable runnable=new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
//要做的事情,这里再次调用此Runnable对象,以实现每两秒实现一次的定时器操作
mHandler.postDelayed(this, 2000);
}
};
mHandler.postDelayed(runnable, 2000);
//mHandler.removeCallbacks(runnable);
核心就是将Runnable提取出来,外层调用
mHandler.postDelayed(runnable, 2000);run方法里面再调用mHandler.postDelayed(this, 2000);
若要实现每次时间累积,如第一次延时2秒,第二次延时4秒,可以考虑用static对象操作。