Android的Handler简析

来源:互联网 发布:调查问卷挣钱知乎 编辑:程序博客网 时间:2024/06/18 16:04

同步自:http://www.elitor.org/?p=201

为什么使用Handler?如何使用Handler?
一个Android程序启动的时候中对应的都有一个主线程Main Thread,也就是UI线程,用于直观显示。当你的程序功能比较复杂,有的时候需要启动别的线程来运行辅助完成一些功能,但是在这些子线程中是不能直接更新UI线程的,否则会抛出一个ViewRootSCalledFromWrongThreadException异常。所以,我们一般的操作是在这个子线程中处理一些事情,处理完了,通过Handler给主线程发送一个message(调用sendMessage()函数完成),而在主线程中将会自动调用handleMessage(Message msg)来处理(没有没什么,这就是Handler的功能),事实上Handler类的这个handleMessage是一个空函数,里面什么事情也没干,查看android的reference便知,所以我们需要自己定义一个类继承Handler,然后override这个函数

总结:
1.需要自己定义一个类继承Handler类,并且override它的handleMessage(Message)函数,可以在这个函数里面实现自己UI的更新等主线程需要的操作。

2.在子线程中通过Handler对象的sendMessage(Message)函数来发送消息给主线程,一旦执行完这个函数,主线程将会自动调用handleMessage(Message)进行操作。
写一个例子:

package org.elitor; import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button; public class HandlerActivity extends Activity{    private Button btn = null;    private MyHandler myHandler = null;     /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState)    {        Log.d("Thread", "Main Thread...");        System.out.println("Main Thread: ThreadID---" + Thread.currentThread().getId());         super.onCreate(savedInstanceState);        setContentView(R.layout.main);         btn = (Button)findViewById(R.id.btn);        myHandler = new MyHandler();         btn.setText("OK");        btn.setOnClickListener(new MyBtnClick());     }     //定义一个MyHandler类继承Handler,override其handleMessage(Message)函数    class MyHandler extends Handler    {         @Override        public void handleMessage(Message msg)        {            // TODO Auto-generated method stub            super.handleMessage(msg);            //打印调试信息            Log.d("Thread", "MyHandler handleMessage...");            System.out.println("MyHandler : ThreadID---" + Thread.currentThread().getId());             btn.setText("handler");            btn.setOnClickListener(new MyBtnClick());        }     }   //定义一个内部线程类MyThread,实现Runnable接口    class MyThread implements Runnable    {         @Override        public void run()        {            // TODO Auto-generated method stub            Log.d("Thread", "MyThread handleMessage...");            System.out.println("MyThread at: ThreadID---" + Thread.currentThread().getId());             //下面四句可以理解为封装一个消息            Message msg = new Message();            Bundle b = new Bundle();            b.putString("value1", "test");            msg.setData(b);             //封装完消息之后,可以通过Handler的对象开始向主线程发送这些消息了            myHandler.sendMessage(msg);        }     }     //还定义一个监听器类,用于监听Button按下事件,实现OnClickListener接口即可    class MyBtnClick implements OnClickListener    {        //一旦绑定Button,如果有click事件将会执行onClick函数        @Override        public void onClick(View v)        {            // TODO Auto-generated method stub            Log.d("BtnClick", "MyButton Clicked...");            //可以在点击Button的时候启动线程            MyThread m = new MyThread();            new Thread(m).start();        }     } }

点击btn的时候将启动线程,在线程里通过handler发送一个消息,主线程通过handleMessage(Message)函数来更新UI,例子中哦给简单的更改了btn的名字。另在例子中加入了几个Log,通过Log我们可以看出handleMessage(Message)函数确实和主线程处于同一线程中,而子线程在别的线程中。



原创粉丝点击