文章目录
一: 原理
不同线程之间的变量是共享的,可以同时进行操作,这造成数据不同步,出现CalledFromWrongThreadException的错误的原因就是进行网络访问和进行UI操作时主,子线程回调错误,可以使用handler自动进行主子线程切换解决。handler是在主线程中创建,则主线程与子线程都可以访问handler里面的数据,在子线程中的message,Bundle,what 被发送到主线程中的messageQueue进行存储,而主线程中的Looper类会执行Loop方法中的一个死循坏把messageQueue中的数据进行执行,如果有message就执行,调用target的dispatchMessage方法回调handlerMessage方法执行数据,否则就一直等待。
下面是胡老师讲解时的图,基本原理流程是子线程发送消息(message)到messageQueue,通过Looper的message的target调用dispatchmessage回调mhandler进行处理数据与操作
handler可以帮助我们进行主线程与子线程的切换,子线程与子线程的切换
二:handler的使用
案例一:下面以实现一个计时器为例
handler代码(放入public class Main2Activity extends AppCompatActivity 里面,onCreate外面)
Handler mhander =new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
if(time>0){
button.setText(time+"秒后可继续发送短信");
time--;
mhander.sendEmptyMessageDelayed(1,1000);
}else {
button.setText("重新发送");
}
}
};
int time=10;
onCreate函数的监听事件
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
time=10;
mhander.sendEmptyMessage(1);
}
});
案例二:如果是传值的话,使用代码如下
Handler mhander =new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
//主线程操作UI进行赋值
String grade =msg.getData().getString("grade");
String classname =msg.getData().getString("classname");
textView11.setText("年级:"+ grade);
textView22.setText("班级:"+classname);
}
};
onCreate函数的
Message message =new Message();
message.what=1;
Bundle bundle=new Bundle();
bundle.putString("grade",grade);//KEY+数据,进行包装数据
bundle.putString("classname",classname);
message.setData(bundle);将数据包装进message
mhander.sendMessage(message);//将值传送过去