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);
        }
    }
}

 

posted @ 2016-04-16 15:28  ts-android  阅读(1121)  评论(0编辑  收藏  举报