一、Handler概述
在安卓中,主线程如果执行一段耗时较长的代码(5-10秒),在这个耗时较长的操作未执行完毕之前,会暂停刷新界面和暂停处理用户操作请求,这时如果用户发出操作请求,就会出现ANR异常(application not response)
执行下面一段代码,程序会出现异常
<span style="font-size:14px;">public class SendMessageActivity extends Activity {
private TextView numberTV;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); // 主线程解析XML, 创建对象, 设置Activity的界面
numberTV = (TextView) findViewById(R.id.numberTV);
}
public void onClick(View v) throws Exception {
new Thread(){
public void run() {
try {
for (int i = 0;; i++) { // 主线程(UI Thread)如果执行一段代码, 那么就会暂停刷新界面和暂停处理用户操作
System.out.println(i); // 后台打印
numberTV.setText(i+"");
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
}</span>android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 这段异常的意思就是只有创建了view对象的线程也就是主线程才能修改这个view,也就是说对界面的修改只能在主线程进行。
碰到这种做耗时操作的时候需要开启新线程, 新线程又需要更新界面, 这时就需要新线程通过Handler和主线程通信。
在实际的应用中,我们会碰到很多耗时的操作,比如读取网络资源,读取数据库,读取联系人等等,这种时候,我们就可以通过使用handler来将新线程和主线程进行通信,来达到及时更新界面的目的。
Handler有两个重要的方法:sendMessage方法和post方法,下面来分别介绍一下这两个方法。
二、sendMessage方法
先在主线程创建一个Handler对象
新线程使用Handler.sendMessage()方法, 可以从新线程向主线程发送一个Message对象(其中可以包含数据)
主线程就会自动执行Handler.handleMessage()方法, 得到Message对象
将上面的程序稍加修改,使用Handler来进行线程之间的通信。
<span style="font-size:14px;">public class SendMessageActivity extends Activity {
private TextView numberTV;
private Handler handler = new Handler(){
public void handleMessage(Message msg) { // 主线程创建Handler对象的子类, 实现了handleMessage()方法
int i = msg.getData().getInt("i"); // 得到Message对象, 获取Bundle, 获取i
numberTV.setText(i + ""); // 主线程设置界面, 只有创建该对象的线程才能修改它
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); // 主线程解析XML, 创建对象, 设置Activity的界面
numberTV = (TextView) findViewById(R.id.numberTV);
}
public void onClick(View v) throws Exception {
new Thread(){
public void run() {
try {
for (int i = 0;; i++) { // 主线程(UI Thread)如果执行一段代码, 那么就会暂停刷新界面和暂停处理用户操作
System.out.println(i); // 后台打印
Message msg = new Message();
msg.getData().putInt("i", i);// 获取Message中的Bundle(Map), 装入数据
handler.sendMessage(msg);// 新线程使用Handler发送Message, 主线程会自动执行handleMessage()方法
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
}</span>如果要修改多个页面,可以用Message类的一个what方法 msg.what 定义不同的常量值赋给不同的msg.what 通过handler对象的sendMessage方法将msg消息发到主线程中去,然后在主线程handler的 handleMessage方法中对接收到的msg作处理,使用msg.what 对不同的值进行响应的操作,就可以完成多个页面的修改。
三、post方法
先在主线程创建一个Handler对象 这时,不需创建子类重写handleMessage方法
新线程使用Handler.post()方法发送一个Runnable对象, 主线程会自动执行Runnable的run()
public class PostActivity extends Activity {
private TextView numberTV;
private Handler handler = new Handler();
private int i;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); // 主线程解析XML, 创建对象, 设置Activity的界面
numberTV = (TextView) findViewById(R.id.numberTV);
}
public void onClick(View v) throws Exception {
new Thread(){
public void run() {
try {
for (i = 0;; i+=2) { // 主线程(UI Thread)如果执行一段代码, 那么就会暂停刷新界面和暂停处理用户操作
System.out.println(i); // 后台打印
handler.post(new Runnable(){ // 新线程使用post()发送一个Runnable给主线程, 主线程自动执行run()
public void run() {
numberTV.setText(i + "");
}
});
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
}
douban.com/note/361619484/
douban.com/note/361619497/
douban.com/note/361619520/
douban.com/note/361619547/
douban.com/note/361619560/
douban.com/note/361619599/
douban.com/note/361619639/
douban.com/note/361619679/
douban.com/note/361619714/
douban.com/note/361619785/
douban.com/note/361619793/
douban.com/note/361619803/
douban.com/note/361619841/
douban.com/note/361619910/
douban.com/note/361619940/
douban.com/note/361619975/
douban.com/note/361620031/
douban.com/note/361620050/
douban.com/note/361620111/
douban.com/note/361620145/
douban.com/note/361620156/
douban.com/note/361620163/
douban.com/note/361620192/
douban.com/note/361620226/
douban.com/note/361618877/
douban.com/note/361619458/
douban.com/note/361619465/
douban.com/note/361619511/
douban.com/note/361619531/
douban.com/note/361619554/
douban.com/note/361619574/
douban.com/note/361619616/
douban.com/note/361619659/
douban.com/note/361619694/
douban.com/note/361619739/
douban.com/note/361619760/
douban.com/note/361619823/
douban.com/note/361619863/
douban.com/note/361619907/
douban.com/note/361619952/
douban.com/note/361619997/
douban.com/note/361620049/
douban.com/note/361620064/
douban.com/note/361620075/
douban.com/note/361620088/
douban.com/note/361620188/
douban.com/note/361620216/
douban.com/note/361620256/
douban.com/note/361620274/
douban.com/note/361620308/
douban.com/note/361620342/
770

被折叠的 条评论
为什么被折叠?



