Handler使用

Handler是android中一个用来处理发送和接受的消息,主要有两个功能:

    1)按计划发送消息或执行某个Runnanble(使用POST方法);

    2)处理消息队列中从其他线程发送来的消息,避免线程冲突(常见于更新UI线程)

  使用Handler之前,首先你要清楚两个问题:

  第一:当一个android应用程序启动时,系统会开启一个主线程,也就是UI线程,这个主线程负责管理界面中的控件,响应用户的操作。

  第二:没有使用另外一个线程启动Handler的时候,Handler是运行在主线程中的,它通过Message对象和子线程进行通信。

  既然Handler默认是运行在主线程中的,说明我们同样不能使用handler处理耗时的操作,否则会出现ANR(Application Not Response)现象。

  那么什么时候会用到Handler呢

  举个例子: 比如我们需要下载一个文件时,这个耗时的操作要放到一个子线程中执行。当文件下载完成后,怎么通知主线程下载完毕呢。

  这个时候,我们可以让子线程发送一个消息给Handler,Handler在收到下载完成的消息时,就可以通知主线程更新UI,通知用户下载完成了。

下面给出一个Handler的小例子,它主要演示

  功能1:   按计划发送消息或执行某个Runnanble(使用POST方法);

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
 
/**
 * @author abing
 * 
 */
public class HandlerTest extends Activity {
    /** Called when the activity is first created. */
    Handler handler = new Handler();
    Runnable updateThread = new Runnable() {
 
        @Override
        public void run() {
            System.out.println("UpdateThread():Thread Id="
                    + Thread.currentThread().getId() + " , Thread Name= "
                    + Thread.currentThread().getName());
            // 延迟3000ms,将需要被执行的线程加入到线程队列中去
            handler.postDelayed(updateThread, 3000);
 
        }
 
    };
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        // 初始化控件
        TextView myTextView = (TextView) findViewById(R.id.myTextView);
 
        Button startButton = (Button) findViewById(R.id.startButton);
        Button endButton = (Button) findViewById(R.id.endButton);
        startButton.setText("start");
        endButton.setText("end");
 
        // 设置监听器
        startButton.setOnClickListener(new StartButtonListener());
        endButton.setOnClickListener(new EndButtonListener());
 
    }
 
    class StartButtonListener implements OnClickListener {
        @Override
        public void onClick(View v) {
            System.out.println("start click():Thread Id="
                    + Thread.currentThread().getId() + " , Thread Name= "
                    + Thread.currentThread().getName());
            handler.post(updateThread);
        }
    }
 
    class EndButtonListener implements OnClickListener {
 
        @Override
        public void onClick(View v) {
            System.out.println("end click():Thread Id="
                    + Thread.currentThread().getId() + " , Thread Name= "
                    + Thread.currentThread().getName());
 
            handler.removeCallbacks(updateThread);
        }
 
    }
 
}

 

  可以看到,在没有特殊声明的情况下,Handler和Main线程是在同一个线程中,下面给出另一个实例,这个实例演示:

  功能2:处理消息队列中从其他线程发送来的消息,避免线程冲突(常见于更新UI线程)

   在这个实例中,我们将处理消息队列的Handler放到一个单独的线程中

 

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
 
/**
 * @author abing
 * 
 */
public class HandlerTest02 extends Activity {
    /** Called when the activity is first created. */
    Handler handler = new Handler();
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        try {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
 
            // 打印当前线程的ID
            System.out.println("Activity Thread :"
                    + Thread.currentThread().getId());
 
            // 开启一个带有looper的线程类,该类实现了使用looper来处理消息队列的功能,这个类由android提供
            HandlerThread handlerThread = new HandlerThread("handler_thread");
            handlerThread.start();
 
            MyHandler myHandler = new MyHandler(handlerThread.getLooper());
            Message msg = myHandler.obtainMessage();
 
            // 使用bundle对象来传递数据
            Bundle b = new Bundle();
            b.putInt("age", 20);
            b.putString("name", "张三");
 
            msg.setData(b);
 
            // 讲msg发送给目标对象,目标对象就是生成该msg的handler对象
            msg.sendToTarget();
 
        } catch (Exception e) {
            e.printStackTrace();
            System.out.print(e.getMessage());
        }
 
    }
 
    /**
     * MyHandler类
     * 
     * @author abing
     * 
     */
    class MyHandler extends Handler {
        public MyHandler() {
        }
 
        /**
         * 此函数的意思是将Handler与looper所在的线程绑定 handler会调用looper所在的线程处理消息
         * 
         * @param looper
         */
        public MyHandler(Looper looper) {
            super(looper);
        }
 
        @Override
        public void handleMessage(Message msg) {
            Bundle b = msg.getData();
            System.out.println("age is : " + b.getInt("age"));
            System.out.println("name is " + b.getString("name"));
            System.out.println("Handler Thread;"
                    + Thread.currentThread().getId());
        }
    }
 
}

 

运行结果:

 

  可以看到,发送消息的线程为1,处理消息的线程的id为9。这样处理消息队列的线程和主线程就分开了。

转载地址:http://www.67tgb.com/?p=451

posted @ 2013-01-09 14:51  麦二蛋  阅读(534)  评论(0编辑  收藏  举报