Handler的使用与UI线程,主线程发送消息给子线程
import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.view.Window; /*目的:开启一个子线程且实现线程之间的通讯(主线程发送消息给子线程的handler处理) handler并不是创建了一个线程,而是在原有的线程上加了一个方法去调用Run方法 所以需要解决这个问题的方法就是利用HandlerThread开启一个线程,再用handler实现通讯 通讯的原因:msg.sendToTarget();--执行对应的--handleMessage方法 */ public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); System.out.println("Activity-->"+Thread.currentThread().getName());//主线程 //实现了使用Looper来处理消息队列的功能 HandlerThread handlerThread=new HandlerThread("handler_Thread"); handlerThread.start();//开启线程 MyHandler myHandler=new MyHandler(handlerThread.getLooper());//必须在上一条代码的下面,这样就是开启了一个新的线程 Message msg = myHandler.obtainMessage();//获取发送信息的对象 msg.arg1=23;//需要发送的数据 msg.obj="abc";//发送对象 Bundle data=new Bundle();//通过捆绑发送更复杂的数据 data.putString("键", "value");//通过键值对是形式捆绑数据 msg.setData(data);//将数据发送出去 //将信息发送到目标对象,目标对象指的是生成msg的对象的对象 msg.sendToTarget();//也就会去执行相对应的handleMessage方法 System.out.println("主线程-->"+Thread.currentThread().getName()); } //创建子线程的handler处理主线程发送来的消息 class MyHandler extends Handler{ @Override public void handleMessage(Message msg) {//处理信息,相当于一个线程 //在子线程运行的,线程名就为handler_Thread(上面创建的) System.out.println("MyhandlerMessage-->"+Thread.currentThread().getName()); int arg=msg.arg1;//通过msg对象获取传过来的数据 String str=(String) msg.obj;//获取数据 Bundle data = msg.getData();//获取捆绑的对象 String string = data.getString("键");//通过键获取值 System.out.println(arg+ str + string); } public MyHandler(Looper looper) { super(looper); } } }
子线程发送消息给主线程的方法见:
Service-服务与线程(第一行代码)包含线程与handler的总结
注意:不能在子线程中创建handler对象,但是....见下面
一些其他运行主线程的方法:
//在子线程中运行主线程的方法
new Thread(new Runnable(){
@Override
public void run() {
System.out.println("子线程名:"+Thread.currentThread().getName());
//run方法里为主线程
handler.post(new Runnable() {
@Override
public void run() {
System.out.println("子线程里的线程名:"+Thread.currentThread().getName());
}
});
//运行UI线程
runOnUiThread(new Runnable(){
@Override
public void run() {
System.out.println("UI线程名:"+Thread.currentThread().getName());
}
});
}
}).start();
1.handler的原理
handler + message + messagequeue + looper
过程(参考原理图)
1. 从消息池中获取message对象,可以设置obj,what,target(指向发送该消息的handler)
2. 先构造handler, 通过handler发送消息(sendMessagAttime(源码中都是调用该方法发送消息))到messagequeue
3.在主线程中的looper中有个loop方法,会不断抽取message中的message
4.把抽取出来的message交给handler的handeMessage方
2.类的说明
handler ,一个线程中可以有多个handler
1.构造方法
1.关联looper,该looper会关联当前线程
2.关联looper中的messagequeue
3.sendMessagAttime将msg发送到与looper关联的messagequeue
4.dispatchMessage该方法会调用handler中handleMessage(需要自己实现并处理数据)
looper类(在Android程序的主线程中会自动的创建一个looper,而且只有一个与该线程对应)
1.构造方法是私有的,会创建一个messagequeue,
2.通过prepare方法创建的对象
3.loop方法
1.是死循环,不断的通过queue.next()抽取消息
2.通过msg.target获得发出该消息的handler,调用handler的dispatchMessage方法
另一种方法实现:主线程发送消息给子线程: 下面给出了子线程发送消息给主线程 和 主线程发送消息给子线程
import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.view.View; public class MainActivity extends Activity { private Handler handlerSon; private Handler handlerUI=new Handler(){ public void handleMessage(Message msg) { System.out.println("收到子线程发送来的消息--当前线程名为:"+Thread.currentThread().getName()); }; }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startThread();//开启子线程,创建handler对象 } private void startThread(){ new Thread(new Runnable(){ @Override public void run() { Looper.prepare();//将handler绑定到当前的子线程,会自动的与当前线程关联 handlerSon=new Handler(){ @Override public void handleMessage(Message msg) { System.out.println("收到主线程发给这个子线程的消息--当前线程名为:"+Thread.currentThread().getName()); } }; Looper.loop();//需要让looper动起来去消息队列中抽取消息 } }).start(); } /** * 单击事件,在主线程中发送消息给子线程,执行子线程中的handleMessage方法(因为handlerSon是在子线程中创建的) */ public void onSendMessagetoSon(View v){ handlerSon.sendEmptyMessage(1); } /** * 单击事件,在子线程中发送消息到主线程,执行主线程的handleMessage方法(因为handlerUI是在主线程中创建的) */ public void onSendMessagetoUI(View v){ new Thread(new Runnable(){ @Override public void run() { handlerUI.sendEmptyMessage(1); } }).start(); } }
效果:
如果需要让子线程执行完再执行主线程,可以使用:
/*join: 当A线程执行到了B线程的.join()方法时,A就回等待,等B线程执行完,A线程才会执行。 join可以用来临时加入线程执行 Thread.yield();//暂停当前线程 t1.setPriority(Thread.MAX_PRIORITY);将t1设置为最低优先级10 默认为5 最高为1 */ public class Test8 { public static void main(String[] args)throws Exception { Demo8 d=new Demo8(); Thread t1=new Thread(d); Thread t2=new Thread(d); t1.start(); t2.start(); t1.join();//代表t1抢到主线程的执行权,主线程没得执行权被处于冻结状态,等t1执行完所有程序,主线程才活过来 for(int x=0;x<80;x++){ System.out.println("main...."+x); } System.out.println("over"); } } class Demo8 implements Runnable{ public void run(){ for(int x=0;x<70;x++){ System.out.println(Thread.currentThread().getName()+"..."+x); } } }