1.在Activity中如果new一个无参的Handler对象,那么这个Handler将自动与当前运行线程相关联,也就是说这个Handler将与当前运行的线程使用同一个消息队列,并且可以处理该队列中的消息。
private Handler handler =new Handler();
public class MainActivity extends Activity {
private String TAG = "main";
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.d(TAG, "mainActivity:" + Thread.currentThread().getId());
handler.post(r);
}
Runnable r = new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
Log.d(TAG, "runnable:" + Thread.currentThread().getId());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}
输出结果:
| 01-04 14:24:12.716: DEBUG/main(12490): mainActivity:1 01-04 14:24:14.758: DEBUG/main(12490): runnable:1 |
通过输出结果可以发现,Runnable对象和主用户界面线程的ID是相同。在这个例子中,我们直接利用handler对象post了一个runnable对象,相当于直接调用了Runnable对象的run函数,也就说没有经过start函数调用run(),那么就不会创建一个新线程,而是在原有线程内部直接调用run()方法,因此输出的线程Id是相同的。
2.如果new一个带参构造函数的Handler对象,那么这个Handler对象将与参数所表示的Looper相关联(摘抄百度)
privateMyHandlermyhandler =newMyHandler(thread.getLooper());
public class HandlerTest2 extends Activity {
private MyHandler myhandler = null;
private String TAG = "main";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.main);
Log.d(TAG, "main:" + Thread.currentThread().getId());
HandlerThread thread = new HandlerThread("MyThread");
thread.start();
myhandler = new MyHandler(thread.getLooper());
Message msg = myhandler.obtainMessage();
msg.sendToTarget();
}
class MyHandler extends Handler {
public MyHandler() {
}
public MyHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
Log.d(TAG, "handler:" + Thread.currentThread().getId());
}
}
}输出结果
| 01-04 14:33:42.753: DEBUG/main(12561): main:101-04 14:33:42.753: DEBUG/main(12561): handler:10 |
根据输出结果,可以看出,新线程Id与主用户界面的线程Id不同。由于我们调用了thread.start()方法,真正的创建了一个新线程,与原来的线程处于不同的线程上下文中,因此打印输出的线程Id是不同的。
同时,MyHandler与HandlerThread 使用的是同一个线程池
3.主线程与子线程- 主线程looper声明的无参数的Handler对讲,刷新界面
public class HandlerTest3 extends Activity {
private String TAG = "main";
@SuppressLint("HandlerLeak")
private Handler myhandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// do something - 刷新ui
Log.d(TAG, "handler:" + Thread.currentThread().getId());
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.main);
Log.d(TAG, "main:" + Thread.currentThread().getId());
myhandler.sendEmptyMessage(0);
new MyThrad().start();
}
private class MyThrad extends Thread {
@Override
public void run() {
super.run();
try {
Log.d(TAG, "thread:" + Thread.currentThread().getId());
Thread.sleep(1000);
// do something - 耗时操作
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}输出结果
| 01-04 14:47:11.762: DEBUG/main(12662): main:1 01-04 14:47:11.772: DEBUG/main(12662): thread:10 01-04 14:47:11.772: DEBUG/main(12662): handler:1 |
根据输出结果,可以看出,主线程Id与子线程Id不同,但是主线程与handler中的线程id一样
即:主线程与handler 使用同一个线程池,looper绑定 子线程是一个
本文深入解析Android应用中线程与Handler之间的交互机制,详细讲解了主线程Handler与子线程Handler的区别及如何实现界面更新。通过实例代码演示,直观展示线程与Handler在不同场景下的应用,帮助开发者掌握Android并发编程的关键点。
845

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



