Android Handler简介及使用 HandlerThread的使用

来源:互联网 发布:用户提高淘宝搜索质量 编辑:程序博客网 时间:2024/06/14 01:52

 在Android系统中,当一个应用程序启动时,首先会启动一个主线程(也被称为UI线程),该线程负责管理界面中的UI控件,进行事件分发,并响应用户的操作。在主线程中不能执行比较耗时的操作(一般不能超过5s),否则Android会认为该应用无响应,便会弹出程序没有响应对话框。如果要执行一些像下载、解析大文件等比较耗时的操作的话,则可以放在Service组件中或放在子线程中执行。这时我们又遇到了一个问题,在Android中不允许在子线程中更新UI组件,UI的更新只能在主线程中执行。Android中为我们提供Handler这个类来解决以上的问题。

 

下面是Handler的详细用法:

1.       Handler简介:

Handler在文档中的定义是:Handler主要用来接收子线程发送的数据,并用此数据配合主线程更新UI。

Handler可以分发Message对象和Runnable对象到主线程中,每个Handler实例,一旦创建后,系统就会把该实例与一个线程和该线程的消息队列绑定带一起,这将可以发送消息和runnable对象给该消息队列,并在消息队列出口处理它们。  当一个进程启动时,主线程独立执行一个消息队列,该队列管理着应用顶层的对象(如:activities、broadcast receivers等等)和所有创建的窗口。你可以创建自己的一个线程,并通过handler来与主线程进行通信。这可以通过在新的线程中调用主线程的handler的post和sendmessage操作来实现。

2.       Handler的用途:

1。按照时间计划,在未来某时刻,对处理一个消息或执行某个runnable实例。

2。把一个对另外线程对象的操作请求放入消息队列中,从而避免线程间冲突。
  

3.  Handler与线程的关系:

       使用Handler的post方法将Runnable对象放到Handler的线程队列中后,该Runnable的执行其实并未单独开启线程,而是仍然在当前Activity线程中执行的,Handler只是调用Runnable对象的run方法。

 

 默认情况下,Handler接受的是当前线程下的消息循环实例(使用Handler(Looper looper)、Handler(Looper looper, Handler.Callback callback)可以指定线程),同时一个消息队列可以被当前线程中的多个对象进行分发、处理(在UI线程中,系统已经有一个Activity来处理了,你可以再起若干个Handler来处理)。在实例化Handler的时候,Looper可以是任意线程的,只要有Handler的指针,任何线程也都可以sendMessage。Handler对于Message的处理不是并发的。一个Looper 只有处理完一条Message才会读取下一条,所以消息的处理是阻塞形式的(handleMessage()方法里不应该有耗时操作,可以将耗时操作放在其他线程执行,操作完后发送Message(通过sendMessges方法),然后由handleMessage()更新UI)

 

消息通过如下方法使用: post(Runnable), postAtTime(Runnable, long), postDelayed(Runnable, long), sendEmptyMessage(int), sendMessage(Message), sendMessageAtTime(Message, long), and sendMessageDelayed(Message, long) 
methods. post之类函数可以传输一个runnable对象给消息队列,并在到达消息队列后被调用。sendmessage之类函数可以传送一个包含数据的message对象,该message对象可以被Handler类的handleMessage(Message) 方法所处理。

     post之类函数和sendmessage之类的函数都可以指定消息的执行时机,是立即执行、稍后一段时间执行,还是在某个确定时刻执行。这可以用来实现超时、消息或其他时间相关的操作。

 

 

下面是一个Demo,使用Handler更新进度条:

package com.xzq;

 

import android.app.Activity;

import android.os.Bundle;

import android.os.Handler;

import android.os.Message;

import android.view.View;

import android.widget.Button;

import android.widget.ProgressBar;

 

public class MainActivity extends Activity {

ProgressBar bar = null;

Button start = null;

 

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        bar = (ProgressBar) findViewById(R.id.progressBar1);

        start = (Button) findViewById(R.id.button1);

        start.setOnClickListener(new View.OnClickListener() {

 

               @Override

               public void onClick(View v) {

                      // TODO Auto-generated method stub

                      bar.setVisibility(View.VISIBLE);

                      updateBar.post(updateThread);

               }

        });

}

 

Handler updateBar = new Handler() {

        @Override

        public void handleMessage(Message msg) {

               bar.setProgress(msg.arg1);

               setTitle("" + msg.arg1);

               updateBar.post(updateThread);

        }

};

Runnable updateThread = new Runnable() {

        int i = 0;

 

        @Override

        public void run() {

               System.out.println("Runnable --> " + Thread.currentThread().getId()

                             + "   " + Thread.currentThread().getName());

               i = i + 10;

               Message msg = updateBar.obtainMessage();

               msg.arg1 = i;

               try {

                      Thread.sleep(1000);

               } catch (InterruptedException e) {

                      e.printStackTrace();

               }

               if (i > 100) {

                      updateBar.removeCallbacks(updateThread);

               }else{

                      updateBar.sendMessage(msg);

               }

        }

};

}

布局:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="vertical" android:layout_width="fill_parent"

    android:layout_height="fill_parent">

    <TextView android:layout_width="fill_parent"

       android:layout_height="wrap_content" android:text="@string/hello" />

    <ProgressBar android:id="@+id/progressBar1"

       android:layout_width="wrap_content" android:layout_height="wrap_content"

       android:visibility="gone" style="?android:attr/progressBarStyleHorizontal"></ProgressBar>

    <Button android:text="开始" android:id="@+id/button1"

       android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>

</LinearLayout>

 

代码比较简单,不做过多介绍了。该实例中Handler是在主线程,也就是UI线程中执行的。

上面说到,Handler可以在其他线程中执行,下面是一个Handler在其他线程中执行的Demo:

       public class HandlerTest2 extends Activity{

       protected void onCreate(Bundle savedInstanceState){

              super.onCreate(savedInstanceState);

              setContentView(R.layout.main);

              System.out.println("Test:   " + Thread.currentThread().getId());;

              //生成一个HandlerThread对象,实现了使用Looper来处理消息队列的功能,这个类由Androi框架提供。

              HandlerThread handlerThread = new HandlerThread("handler_thread");

              handlerThread.start();

              MyHandler myHandler = new MyHandler(handler.getLooper());

              Message msg = new Message();

              //将msg发送到目标对象,所谓的目标对象,就是生成该msg对象的handler对象

              Bundle bundler = new Bundle();

              bundle.putInt("age",22);

              bundle.putString("name","xuzhiqi");

              msg.setData(bundle);

              msg.sendToTarget();

       }

       class myHandler extends Handler{

              public MyHandler(){}

 

              public MyHandler(Looper looper){

                     super(looper);

              }

 

              public void handleMessage(Message msg){

                     Bundle b = msg.getData();

                     int age = b.getInt("age");

                     String name = b.getString("name");

                     System.out.println("age is " + age + ", name is " + name);

                     System.out.println("Handler  -->" + Thread.currentThread().getId());

                     System.out.println("handlerMessage");

              }

       }

}