Android 多线程通信Handler

        在Android中应用到多线程通信,尤其是新的线程去更新主线程的UI,因为新线程无法直接更新widget, 所以在Android多应用handler处理多线程的通信。

Handler主要有两个作用,一是安排消息或者Runnable在某个主线程中某个地方执行,二是安排一个任务去别的线程工作。

提到Handler肯定会设计到Looper,Looper的作用就是替对应的Handler管理消息,每一个Handler都有一个属于自己的Looper,这是一个对一的关系,在Android中除了主线程外其他线程在使用时不会自动为handler分配Looper的,所以在新的线程应用Handler的时候必须首选Looper.prepare函数来初始化Looper,然后用loop()函数来做信息循环的处理。

MessageQueue是控制所属线程的消息,所有的message并不是直接会存储在MeesageQueue中,通过Looper工作的。MessageQueue, Looper

Handler三者是一对一的关系,并且他们三个和某一个所属的线程也是一对一的关系,每个线程都有自己的一套Handler机制 。

具体的消息运行机制是Looper将发出的消息放到MessageQueue中,然后循环的传递给Handler,Handler会将当前的Message进行处理,然后做出相应的反应。

其实无论怎样发送,他们的重点只是一条,用的哪个handler发送的消息,就由这个handler处理消息,这个线程所处的线程做出相应的反应。handler和thread是绑定的一对>一关系。 想让线程接收什么,就用线程所属的handler发送消息。

例如子线程给主线程发送消息更新UI 和主线程给子线程发送信息:


public class MainActivity extends Activity implements OnClickListener {

    private MyHandler mHandler = null;
    private Button btn1;
    private TextView mText;
    private HanderThread myThread;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn1 = (Button) findViewById(R.id.button1);
        mText = (TextView) findViewById(R.id.textview);
        btn1.setOnClickListener(this);
        mHandler = new MyHandler(Looper.getMainLooper());
    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        switch(v.getId()){
        case R.id.button1:
            myThread = new HanderThread();
            myThread.start();
        }
    }

    class MyHandler extends Handler{
        public MyHandler(Looper looper){
            super(looper);
        }

        public void handleMessage(Message msg){
            //此函数处理handler发送的消息。

            switch(msg.what){
            case 4:
                String obj = msg.getData().getString("senddata");
                mText.setText("receive "+obj);
                break;
            default:
                break;
            }
        }
    }

    class HanderThread extends Thread{
        HanderThread (){
        }

        public void run(){

            // 在这里你可以做一些费时的操作,本例只是在这里发送了一个
            //消息给主线程告诉它消息来自子线程,并改变TextView中的文字。

            String msg = "from child thread";
            Bundle mBundle = new Bundle();
            Message Msg = mHandler.obtainMessage();
            mBundle.putString("senddata",msg);
            Msg.what = 4;
            Msg.setData(mBundle);

            //要记住这里发送这个message的是mHandler,这个handler是
            //属于主线程的handler所以主线程来处理这个消息。并且有主线程
            //来做出相应的改变。
            mHandler.sendMessage(Msg);

        }
    }
 
 
    
public class MainActivity extends Activity {

    private Handler mMainHandler = null;
    private TextView info = null;
    private Button msgBtn = null;
    ChildThread child1 = null;

    class ChildThread extends Thread {
        private Handler childHander = null;
        private String CHILD_TAG = "ChildThread";

        public void run() {
            this.setName("ChildThread");

            // 初始化消息循环队列,需要在Handler创建之前
            //必须用这个函数和loop(),否则报错。
            Looper.prepare();

            childHander = new Handler() {
                @Override
                public void handleMessage(Message msg) {

                    // 在子线程中可以做一些耗时的工作
                    String sMsg = "";

                    Message toMain = new Message();

                    // mMainHandler.obtainMessage();
                    toMain.obj = "This message from  "
                            + this.getLooper().getThread().getName()
                            + " the main thread had sent " + (String) msg.obj;

                    // 这个消息是主线程的handler发送的,由主线程处理,这里
                    //主要是改变主线程TextView的文字。
                    mMainHandler.sendMessage(toMain);
                }
            };
            //使消息开始循环。
            Looper.loop();
        }
    }
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        info = (TextView) findViewById(R.id.info);
        msgBtn = (Button) findViewById(R.id.bt1);

        mMainHandler = new Handler() {

            @Override
            public void handleMessage(Message msg) {

                // 处理收到的消息。
                info.setText((String) msg.obj);
            }

        };
        
        child1 = new ChildThread();
        child1.start();
        
        msgBtn.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                if (child1.childHander != null) {

                    // 发送消息给子线程
                    Message childMsg = child1.childHander.obtainMessage();
                    Message msg = new Message();
                    msg.obj = mMainHandler.getLooper().getThread().getName()
                            + " say hello";

                    // 因为发送这个小时的handler是子线程的所有子线程处理。
                    // 哪个线程处理消息要看是由属于哪个线程的handler发出的消息。
                    child1.childHander.sendMessage(msg);
                }
            }
        });

    }
}
 
 
 
 
 
 
 
 
 
 
 

猜你喜欢

转载自blog.csdn.net/alvinhuai/article/details/16826279
今日推荐