Android使用Handler实现子线程与子线程、子线程与主线程之间通信

转载:https://blog.csdn.net/shaoenxiao/article/details/54561753

今天这篇文章只讲一下怎么使用Handler实现子线程与子线程之间、子线程与主线程之间如何进行通信,关于具体的内部实现因为我也没研究过,所以这篇文章讲不了。

一、子线程向主线程传值:

这个实现比较简单,因为主线程自带Looper机制,所有我们不用创建Looper了,看一下代码吧:

首选在主线程里创建一个Handler


   
   
  1. 1.Handler mHandler = new Handler(){
  2. 2.
  3. 3. @Override
  4. 4. public void handleMessage(Message msg) {
  5. 5. super.handleMessage(msg);
  6. 6. switch (msg.what) {
  7. 7. case 0:
  8. 8. //do something,refresh UI;
  9. 9. break;
  10. 10. default:
  11. 11. break;
  12. 12. }
  13. 13. }
  14. 14.
  15. 15.};
然后开启一个子线程,在子线程里直接使用Handler发送消息即可

   
   
  1. new Thread() {
  2. public void run() {
  3. Message message = new Message();
  4. message.obj = "子线程发送的消息Hi~Hi";
  5. mHandler .sendMessage(message);
  6. };
  7. }.start();

二、主线程向子线程里发送消息:

主线程向子线程发送消息的话,我们需要在子线程里初始化Looper,并在主线程里创建的Handler引用子线程的Looper(Handler中引用的是哪个线程的Looper,就在哪个线程里处理消息),下面看代码:


   
   
  1. public class ThreadHandlerActivity extends Activity{
  2. //创建子线程
  3. class MyThread extends Thread{
  4. private Looper looper; //取出该子线程的Looper
  5. public void run() {
  6. Looper.prepare(); //创建该子线程的Looper
  7. looper = Looper.myLooper(); //取出该子线程的Looper
  8. Looper.loop(); //只要调用了该方法才能不断循环取出消息
  9. }
  10. }
  11. private Handler mHandler; //将mHandler指定轮询的Looper
  12. protected void onCreate(Bundle savedInstanceState) {
  13. super.onCreate(savedInstanceState);
  14. setContentView(R.layout.main);
  15. thread = new MyThread();
  16. thread.start(); //千万别忘记开启这个线程
  17. //下面是主线程发送消息
  18. mHandler = new Handler(thread.looper){
  19. public void handleMessage(android.os.Message msg) {
  20. Log.d( "当前子线程是----->",Thread.currentThread()+ "");
  21. };
  22. };
  23. mHandler.sendEmptyMessage( 1);
  24. }
  25. }
其实这样就可以达到主线程向子线程发送消息了,然而当我们运行后发现程序会Crash掉,报了一个控制针,这是因为在Handler初始化的时候,thread.looper还没有初始化,所以会报控制针,这时我们可以让主线程等待一下子线程,也可以来一个while循环来判断thread.looper是否初始化完成。不过Android本身还提供了一个方法,那就是 HandlerThread

   
   
  1. protected void onCreate(Bundle savedInstanceState) {
  2. super.onCreate(savedInstanceState);
  3. tv = new TextView( this);
  4. tv.setText( "Handler实验");
  5. setContentView(tv);
  6. //实例化一个特殊的线程HandlerThread,必须给其指定一个名字
  7. HandlerThread thread = new HandlerThread( "handler thread");
  8. thread.start(); //千万不要忘记开启这个线程
  9. //将mHandler与thread相关联
  10. mHandler = new Handler(thread.getLooper()){
  11. public void handleMessage(android.os.Message msg) {
  12. Log.d( "当前子线程是----->", Thread.currentThread()+ "");
  13. };
  14. };
  15. mHandler.sendEmptyMessage( 1); //发送消息
  16. }
这时HandlerMessage所在的线程就是HandlerThread 的子线程。
然而HandlerThread 所创建处理的子线程里是不能重写Run()方法的,你写了以后,会发现,HandlerMessage不执行了,这时因为HandlerMessage本身实现了Run()方法,我们看一下内部实现:

   
   
  1. @Override
  2. public void run() {
  3. mTid = Process.myTid();
  4. Looper.prepare();
  5. synchronized ( this) {
  6. mLooper = Looper.myLooper();
  7. notifyAll();
  8. }
  9. Process.setThreadPriority(mPriority);
  10. onLooperPrepared();
  11. Looper.loop();
  12. mTid = - 1;
  13. }

在源代码的第4行,进行了实例化自己的Looper,如果继续追踪源代码翻看其getLooper方法你会发现,如果一个Handler在与HandlerThread进行绑定时,发现Looper为空,Handler则会一直等待直到Looper被创建出来为止,然后才继续执行后续的代码。所以我们重写了HandlerThread的run方法,肯定就不会去创建Looper对象,那么绑定的Handler就会永远处于等待状态,自然而然就不会执行到HandlerMessage信息了。这也是为什么我们要使用HandlerThread这个特殊的线程,因为使用这个,我们不必关心多线程会混乱,Looper会为空等一系列问题,只要去关心我们要实现的逻辑就行了。

三、子线程和子线程之间通信:

其实子线程向子线程之间通信,其实就是在一个子线程中创建一个Handler,它的回调自然就在此子线程中,然后在另一个子线程中调用此handler来发送消息就可以了,不过记得写上Looper哦,下面看代码:


   
   
  1. new Thread( new Runnable() {
  2. @Override
  3. public void run() {
  4. String msg;
  5. Looper.prepare();
  6. childHandler = new Handler() {
  7. @Override
  8. public void handleMessage(Message msg) {
  9. super.handleMessage(msg);
  10. System.out.println( "这个消息是从-->>" + msg.obj+ "过来的,在" + "btn的子线程当中" + "中执行的");
  11. }
  12. };
  13. Looper.loop(); //开始轮循
  14. }
  15. }).start();

其中 Looper.prepare()和Looper.loop()一定不要忘了写。

然后我们创建第二个子线程


   
   
  1. new Thread( new Runnable() {
  2. @Override
  3. public void run() {
  4. Looper loop = Looper.myLooper();
  5. Message msg = childHandler.obtainMessage();
  6. msg.obj = "btn2当中子线程";
  7. childHandler.sendMessage(msg);
  8. }
  9. }).start();







评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值