Android Handler实现子线程与子线程、主线程之间通信
一、子线程向主线程传值:
首选在主线程里创建一个Handler
1 Handler mHandler = new Handler(){ 2 @Override 3 public void handleMessage(Message msg) { 4 super.handleMessage(msg); 5 switch (msg.what) { 6 case 0: 7 //do something,refresh UI; 8 break; 9 default: 10 break; 11 } 12 } 13 };
- 然后开启一个子线程,在子线程里直接使用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 7 Looper.prepare();//创建该子线程的Looper 8 looper = Looper.myLooper();//取出该子线程的Looper 9 Looper.loop();//只要调用了该方法才能不断循环取出消息 10 } 11 } 12 13 private Handler mHandler;//将mHandler指定轮询的Looper 14 15 protected void onCreate(Bundle savedInstanceState) { 16 super.onCreate(savedInstanceState); 17 setContentView(R.layout.main); 18 thread = new MyThread(); 19 thread.start();//千万别忘记开启这个线程 20 //下面是主线程发送消息 21 mHandler = new Handler(thread.looper){ 22 public void handleMessage(android.os.Message msg) { 23 Log.d("当前子线程是----->",Thread.currentThread()+""); 24 }; 25 }; 26 mHandler.sendEmptyMessage(1); 27 } 28 29 }
其实这样就可以达到主线程向子线程发送消息了,然而当我们运行后发现程序会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 7 //实例化一个特殊的线程HandlerThread,必须给其指定一个名字 8 HandlerThread thread = new HandlerThread("handler thread"); 9 thread.start();//千万不要忘记开启这个线程 10 //将mHandler与thread相关联 11 mHandler = new Handler(thread.getLooper()){ 12 public void handleMessage(android.os.Message msg) { 13 Log.d("当前子线程是----->", Thread.currentThread()+""); 14 }; 15 }; 16 mHandler.sendEmptyMessage(1);//发送消息 17 }
这时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 3 @Override 4 public void run() { 5 String msg; 6 Looper.prepare(); 7 8 childHandler = new Handler() { 9 @Override 10 public void handleMessage(Message msg) { 11 super.handleMessage(msg); 12 13 System.out.println("这个消息是从-->>" + msg.obj+ "过来的,在" + "btn的子线程当中" + "中执行的"); 14 15 } 16 17 }; 18 Looper.loop();//开始轮循 19 20 } 21 }).start();
- 其中 Looper.prepare()和Looper.loop()一定不要忘了写。
然后我们创建第二个子线程
1 new Thread(new Runnable() { 2 3 @Override 4 public void run() { 5 Looper loop = Looper.myLooper(); 6 Message msg = childHandler.obtainMessage(); 7 msg.obj = "btn2当中子线程"; 8 childHandler.sendMessage(msg); 9 } 10 }).start();
本文来自博客园,作者:Bytezero!,转载请注明原文链接:https://www.cnblogs.com/Bytezero/p/16470948.html