Android入门教程 handler的用法

本文讲解Android中Handler的使用,要讲清楚Handler,就需要附带引入几个概念——Looper、MessageQueue、Message。

一、为什么要用Handler

大家都知道,每一个Android应用启动时,都会启动一个UI线程(也叫主线程)。只有在UI线程里才可以对控件、布局进行获取或设置。

另外,在Android的设计思想中,为了确保流畅的操作体验。一些耗时的任务不能够在UI线程中运行,需要用户单独开一个子线程,这些耗时的操作在子线程中执行。

那么问题来了——子线程执行过程中或者执行结束后,如果需要修改UI,该怎么做呢?(例如:下载完成后,需要将TextView修改为“下载完毕”)
这个时候,我们就需要用到Handler消息传递机制了。

二、什么是Handler

Handler是Android SDK中处理异步消息的核心类。

Handler的作用是让子线程通过与UI线程通信来更新UI界面(也就是说解决子线程不能更新UI的问题)。

主线程 中使用Handler很简单,举个例子。

    private Handler tvHandler = new Handler(){
        public void handleMessage(Message msg) {
            textview.setText("下载完成");
        };
    };

三、什么是Message、MessageQueue

刚才说到子线程需要与UI线程进行通信,所以才有了Handler消息传递机制,那么既然要通信,肯定要有个信使,Message就是担当了信使的作用。

通信过程中可能会有多条消息发送出去,所以就有了MessageQueue,即消息队列。

消息队列里面有很多条消息,那么先处理谁后处理谁呢?这就需要用到Looper。

四、什么是Looper

Looper就是负责管理MessageQueue的一个工具,会不断地从MessageQueue中取出消息,并将消息分给对应的Handler处理。

每个线程只有一个Looper.

五、为什么有的地方不需要使用Looper

也许大家会有个疑问——我也用到了Handler,但是我没有用Looper啊,这是为什么?

在UI线程中,系统已经初始化了一个Looper对象,因此不需要我们手动创建,直接使用Handler就可以了。

但是,假如你在子线程中使用Handler,则必须手动创建一个Looper对象,并启动它。

Looper.prepare();//创建Looper对象
//...
Looper.loop();//启动Looper

所以,在子线程中使用Handler的步骤如下:

  1. 调用Looper.prepare()方法,创建Looper对象。此时系统会自动为其创建配套的MessageQueue。
  2. 有了Looper之后,创建Handler,重写handlerMessage()方法。
  3. 调用Looper.loop()方法启动Looper。

六、实例演示

1、在主线程中使用Handler模拟下载

public class DownLoadActivity extends Activity {

    private TextView countTV;
    private TextView finishTV;

    private int count;

    //在主线程中创建Handler实例
    private Handler handler = new Handler(){
        //handlerMessage方法负责接收子线程传来的消息
        public void handleMessage(android.os.Message msg) {

            if(msg.what==1){
                countTV.setText(count+"%");
            }else if(msg.what==2){
                finishTV.setText("下载完成");
            }
        };
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_down_load);
        bindID();

        //启动子线程
        new Thread(new Runnable() {

            @Override
            public void run() {

                while(count<100){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //通过sendEmptyMessage方法发送消息
                    handler.sendEmptyMessage(1);
                    count+=10;
                }
                //下载完成后,再次发送消息
                handler.sendEmptyMessage(2);
            }
        }).start();

    }


    private void bindID() {
        countTV = (TextView) findViewById(R.id.downloadCount);
        finishTV = (TextView) findViewById(R.id.finishTV);
    }
}

2、在主线程、子线程中均使用Handler模拟质数的计算

public class CalculateActivity extends Activity {

    private EditText editText;
    private Button btn;
    private TextView textview;

    private ArrayList<Integer> nums ;

    private int upperNum;

    CalThread cThread;//子线程


    //主线程中创建Handler实例,更新UI
    private Handler tvHandler = new Handler(){
        public void handleMessage(Message msg) {
            textview.setText(nums.toString());
        };
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_calculate);

        bindID();

        //实例化子线程
        cThread = new CalThread();
        //启动线程
        cThread.start();

        btn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                upperNum = Integer.parseInt(editText.getText().toString());
                //获取消息对象,使用obtainMessage而非new Message(),这样能减小内存开支
                Message msg = cThread.calHandler.obtainMessage();
                msg.arg1 = 1;
                msg.arg2 = 2;
                msg.what = 3;
                //发送消息至子线程的Handler
                cThread.calHandler.sendMessage(msg);
            }
        });

    }

    private void bindID() {
        editText = (EditText) findViewById(R.id.num_edit);
        btn = (Button) findViewById(R.id.btn);
        textview = (TextView) findViewById(R.id.num_text);
    }

    /**
     * 计算质数的方法
     */
    private void calc() {
        nums = new ArrayList<Integer>();
        A: for (int i = 1; i <= upperNum; i++) {
            for (int j = 2; j < Math.sqrt(i); j++) {
                if (i != 2 && i % j == 0) {
                    continue A;
                }
            }
            nums.add(i);
        }
    }

    class CalThread extends Thread {

        Handler calHandler;

        @Override
        public void run() {
            Looper.prepare();
            System.out.println("run..........");
            calHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {

                    System.out.println("handleMessage............."+msg);
                    System.out.println(msg.arg1+"*"+msg.arg2+"*"+msg.what+"*"+msg.getWhen()+"*"+SystemClock.uptimeMillis());

                    //计算质数是个耗时操作,所以要在子线程中执行
                    calc();

                    Toast.makeText(CalculateActivity.this, nums.toString(), Toast.LENGTH_LONG).show();
                    //计算质数完成后,发送消息给主线程Handler,要求其更新UI
                    tvHandler.sendEmptyMessage(1);
                }
            };

            Looper.loop();
        }
    }

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值