线程两大规则
1.在主线程中使用sleep()不能超过五秒时,否则可能会导致android干预,弹出ANR
2.视图的修改必须在主线程中否则会抛出异常:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
解决办法:
2.1.线程之间的消息传递Message,Handler
这时候就需要用到Message。
例如,在制作进入条ProgressBar时,需要在进度条下的TextView中实时改变它的text,进度条用线程实现,在其中不能使用TextView.setText(“XXX”),否则会报上述异常,上述异常的原因是说只能在原始线程上修改,这时就需要线程之间的消息传递者:Message,以下给出部分代码:
//进度条的线程及传出消息
public void run() {
while (progress<100){
progress++;
progressBar1.setProgress(progress);
Message message =new Message();
//开始传递消息
message.obj =progress;
message.what =CHANGE;
message.setTarget(handler);
message.sendToTarget();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//创建消息接收器,创建在哪里就在哪个线程
Handler handler =new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case CHANGE:
//设置Textiew
textView1.setText(msg.obj + "%");
break;
}
}
};
需要注意的是Message的接收器Handle(android.os.Handler)与要修改的控件在同一线程。
2.1.1Message初始化的方法
1.大众熟悉的new Message(),不过效率低
2.handler.obtainMessage();效率高
补充:在需要重复发送消息时,必须重新初始化一个message,否则会抛出异常:
java.lang.IllegalStateException: The specified message queue synchronization barrier token has not been posted or has already been removed.
//message没被设置或已被删除
2.2.使用view.post
在Thread.run()中使用此方法,会在Thread结束后将此方法放入主线程的线程任务中,这样不违反第二原则
线程中使用synchronized锁定代码段
在安卓中为了线程安全,让多个线程不至于同时重复使用同一代码段而出现异常,往往在类中定义一个锁定对象(Object object =new Object()),之后使用
synchronized (object) {
//要锁定的代码块
}
锁定代码