考虑这个问题的原因:子线程不能更新UI
子线程向主线程传值:发送消息
new Thread() { public void run() { Message message = new Message(); message.obj = "你好主线程,我是子线程"; mHandler .sendMessage(message); }; }.start();
(讲一下handler的另一个方法,post,是直接post一个线程进队列,逻辑线程自己执行。)
所以只要在主线程里接受一下就可以更新UI了
private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { //更新UI } };
下面借鉴自http://blog.csdn.net/shaoenxiao/article/details/54561753?utm_source=itdadao&utm_medium=referral
主线程向子线程传值:
这个时候需要为子线程创建一个looper(主线程中是不需要的,本来就封装好的)
class MyThread extends Thread{ private Looper looper;//取出该子线程的Looper public void run() { Looper.prepare();//创建该子线程的Looper looper = Looper.myLooper();//取出该子线程的Looper Looper.loop();//只要调用了该方法才能不断循环取出消息 } }
然后子线程有了looper,handler就可以指定消息发到这个线程里了
private Handler mHandler;//将mHandler指定轮询的Looper protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); thread = new MyThread(); thread.start();//千万别忘记开启这个线程 //下面是主线程发送消息 mHandler = new Handler(thread.looper){ public void handleMessage(android.os.Message msg) { Log.d("当前子线程是----->",Thread.currentThread()+""); }; }; mHandler.sendEmptyMessage(1); }但是代码是有错的,很容易就知道是空指针。子线程的looper用来告诉handler消息要发送到哪。thread.looper。主线程执行到这里的时候,虽然那个子线程已经开启了,但是他绝对没有主线程跑得快,所以就空指针了。
这个时候主线程等待子线程肯定是不正确的做法,用一个while循环也是一个不太可行的做法,用HandlerThread是最优的选项。
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); tv = new TextView(this); tv.setText("Handler实验"); setContentView(tv); //实例化一个特殊的线程HandlerThread,必须给其指定一个名字 HandlerThread thread = new HandlerThread("handler thread"); thread.start();//千万不要忘记开启这个线程 //将mHandler与thread相关联 mHandler = new Handler(thread.getLooper()){ public void handleMessage(android.os.Message msg) { Log.d("当前子线程是----->", Thread.currentThread()+""); }; }; mHandler.sendEmptyMessage(1);//发送消息 }他的源码是一直等到这个子线程的looper对象被创建出来以后才会执行后续代码。
子线程间的通信:(最好学一下AIDL)
就是声明一个成员变量的handler,两个子线程间公用它就行了。一个负责new出那个handler,一个使用那个handler。
new Thread(new Runnable() { @Override public void run() { String msg; Looper.prepare(); childHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); System.out.println("这个消息是从-->>" + msg.obj+ "过来的,在" + "btn的子线程当中" + "中执行的"); } }; Looper.loop();//开始轮循 } }).start();
new Thread(new Runnable() { @Override public void run() { Looper loop = Looper.myLooper(); Message msg = childHandler.obtainMessage(); msg.obj = "btn2当中子线程"; childHandler.sendMessage(msg); } }).start();
还有在子线程中更新UI还可以About_Activity.this.runOnUiThread(new Runnable() ,asynctask
最后总结下
1.mHandler.post
2.mHandler.sendMessage
3.runOnUiThread(本质上也是调用了post)
4.view.post(view自己封装的异步机制)