`
DanielHan
  • 浏览: 57110 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
074641d7-eb86-343f-a745-65a0f693edb5
设计模式
浏览量:7364
社区版块
存档分类
最新评论

Handler

阅读更多
    Android中有着和J2SE同样优秀的多线程支持,可以把那些耗时较多的操作放在新线程中操作。但是当新线程中有涉及到操作UI的操作时,就会对主线程产生危险,因此,Android提供了Handler作为主线程和子线程的纽带。同时,Handler对象初始化后,就默认与对它初始化的进程的消息队列绑定,因此可以利用Handler所包含的消息队列,制定一些操作的顺序。
下面,就Handler的以上两点作用,分别进行讨论。
1. 传递Message。用于接受子线程发送的数据, 并用此数据配合主线程更新UI。   
    在Android中,对于UI的操作通常需要放在主线程中进行操作。如果在子线程中有关于UI的操作,那么就需要把数据消息作为一个Message对象发送到消息队列中,然后,有Handler中的handlerMessge方法处理传过来的数据信息,并操作UI。当然,Handler对象是在主线程中初始化的,以为它需要绑定在主线程的消息队列中。
    类sendMessage(Message msg)方法实现发送消息的操作。 在初始化Handler对象时重写的handleMessage方法来接收Messgae并进行相关操作。

//Handler处理子线程消息代码示例:  
 
public class Activity01 extends Activity  
{  
    //声明ProgressBar对象  
    private ProgressBar m_ProgressBar;  
    private ProgressBar m_ProgressBar2;  
    private Button mButton01;  
    protected static final int GUI_STOP_NOTIFIER = 0x108;  
    protected static final int GUI_THREADING_NOTIFIER = 0x109;  
    public int intCounter=0;  
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState)  
    {  
        super.onCreate(savedInstanceState);  
        //设置窗口模式,,因为需要显示进度条在标题栏  
        requestWindowFeature(Window.FEATURE_PROGRESS);  
        setProgressBarVisibility(true);  
        setContentView(R.layout.main);  
          
        //取得ProgressBar  
        m_ProgressBar = (ProgressBar) findViewById(R.id.ProgressBar01);  
        m_ProgressBar2= (ProgressBar) findViewById(R.id.ProgressBar02);  
        mButton01 = (Button)findViewById(R.id.Button01);   
          
        m_ProgressBar.setIndeterminate(false);  
        m_ProgressBar2.setIndeterminate(false);  
          
        //当按钮按下时开始执行,  
        mButton01.setOnClickListener(new Button.OnClickListener()  
        {  
          @Override 
          public void onClick(View v)  
          {  
            // TODO Auto-generated method stub  
                
              //设置ProgressBar为可见状态  
              m_ProgressBar.setVisibility(View.VISIBLE);  
              m_ProgressBar2.setVisibility(View.VISIBLE);  
              //设置ProgressBar的最大值  
              m_ProgressBar.setMax(100);  
              //设置ProgressBar当前值  
              m_ProgressBar.setProgress(0);  
              m_ProgressBar2.setProgress(0);  
 
              //通过线程来改变ProgressBar的值  
  new Thread(new Runnable() {  
     public void run()  
        {  
     for (int i = 0; i < 10; i++)  
        {  
           try 
           {  
                 intCounter = (i + 1) * 20;  
                 Thread.sleep(1000);  
 
            if (i == 4)  
            {  
            Message m = new Message();  
 
             m.what = Activity01.GUI_STOP_NOTIFIER;  
            Activity01.this.myMessageHandler.sendMessage(m);
   //将message发送到消息队列  
              break;  
             }  
            else 
           {  
           Message m = new Message();  
           m.what = Activity01.GUI_THREADING_NOTIFIER;  
           Activity01.this.myMessageHandler.sendMessage(m);  
  //将message发送到消息队列  
                                }  
                            }  
                            catch (Exception e)  
                            {  
                                e.printStackTrace();  
                            }  
                        }  
                    }  
                }).start();  
            }  
        });  
    }  
 
//通过匿名类复写Handler类中的handleMessage方法,用于接收传递到消息队列中的Message,并进行UI操作。
      Handler myMessageHandler = new Handler()  
      {  
        // @Override   
          public void handleMessage(Message msg)  
          {  
              switch (msg.what)  
              {  
              //ProgressBar已经是对大值  
              case Activity01.GUI_STOP_NOTIFIER:  
                  m_ProgressBar.setVisibility(View.GONE);  
                  m_ProgressBar2.setVisibility(View.GONE);  
                  Thread.currentThread().interrupt();  
                  break;  
              case Activity01.GUI_THREADING_NOTIFIER:  
                  if (!Thread.currentThread().isInterrupted())  
                  {  
                      // 改变ProgressBar的当前值  
                      m_ProgressBar.setProgress(intCounter);  
                      m_ProgressBar2.setProgress(intCounter);  
                        
                      // 设置标题栏中前景的一个进度条进度值  
                      setProgress(intCounter*100);  
                      // 设置标题栏中后面的一个进度条进度值  
                      setSecondaryProgress(intCounter*100);//  
                  }  
                  break;  
              }  
              super.handleMessage(msg);  
         }  
      };  
} 

以上的例子中,子线程只是对进度条的参数进行了变更,并将结果以message形式发送到消息队列中去,子线程的内部并未进行UI操作,而是在重写的Handler的handlerMessage方法中操作了UI界面。
   2. 传递Runnable对象。用于通过Handler绑定的消息队列,安排不同操作的执行顺序。
    Handler对象在进行初始化的时候,会默认的自动绑定消息队列。利用类post方法,可以将Runnable对象发送到消息队列中,按照队列的机制按顺序执行不同的Runnable对象中的run方法。

public class HandlerActivity extends Activity {  
    /** Called when the activity is first created. */ 
    //声明两个按钮控件  
    private Button startButton = null;  
    private Button endButton = null;  
    @Override 
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
        //根据控件的ID得到代表控件的对象,并未这两个按钮设置相应的监听器  
        startButton = (Button)findViewById(R.id.startButton);  
        startButton.setOnClickListener(new StartButtonListener());  
        endButton = (Button)findViewById(R.id.endButton);  
        endButton.setOnClickListener(new EndButtonListener());  
          
    }  
    class StartButtonListener implements OnClickListener{  
 
        @Override 
        public void onClick(View v) {  
            //调用Handler的post方法,将要执行的线程对象添加到队列当中  
            handler.post(updateThread);  
        }  
          
    }  
      
    class EndButtonListener implements OnClickListener{  
 
        @Override 
        public void onClick(View v) {  
            handler.removeCallbacks(updateThread);  
        }  
          
    }  
    //创建一个Handler对象  
    Handler handler  = new Handler();  
    //将要执行的操作写在线程对象的run方法当中  
    Runnable updateThread =  new Runnable(){  
 
        @Override 
        public void run() {  
            System.out.println("UpdateThread");  
            //在run方法内部,执行postDelayed或者是post方法  
            handler.postDelayed(updateThread, 3000);  
        }  
          
    };  
} 

程序的运行结果就是每隔3秒钟,就会在控制台打印一行UpdateTread。这是因为实现了Runnable接口的updateThread对象进入了空的消息队列即被立即执行run方法,而在run方法的内部,又在3000ms之后将其再次发送进入消息队列中。
   3. Handler和多线程
    post方法虽然发送的是一个实现了Runnable接口的类对象,但是它并非创建了一个新线程,而是执行了该对象中的run方法。也就是说,整个run中的操作和主线程处于同一个线程。
    这样对于那些简单的操作,似乎并不会影响。但是对于耗时较长的操作,当它被加入到消息队列中之后执行会占用很长的时间,以至于处于同一线程的其他操作无法继续执行,就会出现“假死”。为了解决这个问题,就需要使得handler绑定到一个新开启线程的消息队列上,在这个处于另外线程的上的消息队列中处理传过来的Runnable对象和消息。

public class HandlerTest2 extends Activity {  
 
    @Override 
    protected void onCreate(Bundle savedInstanceState) {  
        // TODO Auto-generated method stub  
    super.onCreate(savedInstanceState);  
    setContentView(R.layout.main);  
    //打印了当前线程的ID  
    System.out.println("Activity-->" + Thread.currentThread().getId());  
    //生成一个HandlerThread对象  
    HandlerThread handlerThread = new HandlerThread("handler_thread");  
    //在使用HandlerThread的getLooper()方法之前,必须先调用该类的start(),同时开启一个新线程;  
    handlerThread.start();
    //将由HandlerThread获取的Looper传递给Handler对象,即由处于另外线程的Looper代替handler初始化时默认绑定的消息队列来处理消息。  
    MyHandler myHandler = new MyHandler(handlerThread.getLooper());  
    Message msg = myHandler.obtainMessage();  
    //将msg发送到目标对象,所谓的目标对象,就是生成该msg对象的handler对象  
    Bundle b = new Bundle();  
    b.putInt("age", 20);  
    b.putString("name", "Jhon");  
    msg.setData(b);  
    msg.sendToTarget();  //将msg发送到myHandler
    }  
      
    //定义类
    class MyHandler extends Handler{  
    public MyHandler(){  
              
    }  
    
    public MyHandler(Looper looper){  
        super(looper);  
    }  
    @Override 
    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");  
        }  
    }  
}

这样,当使用sendMessage方法传递消息或者使用post方法传递Runnable对象时,就会把它们传递到与handler对象绑定的处于另外一个线程的消息队列中,它们将在另外的消息队列中被处理。而主线程还会在发送操作完成时候继续进行,不会影响当前的操作。
    这里需要注意,这里用到的多线程并非由Runnable对象开启的,而是ThreadHandler对象开启的。Runnable对象只是作为一个封装了操作的对象被传递,并未产生新线程
分享到:
评论

相关推荐

    Fragment与Activity使用Handler进行交互

    在这种情况下,Handler机制可以作为一个有效的工具来实现线程间的通信。本文将深入探讨如何在Fragment和Activity之间使用Handler进行交互。 首先,了解Handler的基本概念。Handler是Android中的一个消息处理类,它...

    android 中Handler 的几种写法

    在Android开发中,`Handler`是一个至关重要的组件,它用于在主线程中处理来自其他线程的消息,确保UI更新和事件处理的同步性。本文将详细介绍`Handler`的几种常见写法,以及如何使用`Handler.Callback`进行消息处理...

    jobHandler调度器

    "JobHandler调度器"是一种广泛应用于分布式任务调度的框架,主要设计用于处理大规模并发和定时任务的场景。在这个系统中,JobHandler是核心组件,它负责执行具体的业务逻辑。下面我们将详细探讨JobHandler调度器的...

    Foxit PDF Preview Handler

    Foxit PDF Preview Handler 是一款专为Outlook 2007设计的插件,它使得用户可以在不离开邮件客户端的情况下预览PDF附件。这款工具极大地提升了处理PDF文档的效率,尤其是在处理大量PDF邮件附件时,避免了频繁打开...

    netty-handler-4.1.68.Final-API文档-中文版.zip

    赠送jar包:netty-handler-4.1.68.Final.jar; 赠送原API文档:netty-handler-4.1.68.Final-javadoc.jar; 赠送源代码:netty-handler-4.1.68.Final-sources.jar; 赠送Maven依赖信息文件:netty-handler-4.1.68....

    一个activity中多个handler和消息的处理过程

    在Android应用开发中,Activity是用户界面的主要载体,而Handler机制则是实现异步通信和更新UI的关键工具。本文将深入探讨在一个Activity中如何管理和处理多个Handler以及它们的消息流程。 首先,Handler是Android...

    netty-handler-4.1.73.Final-API文档-中文版.zip

    赠送jar包:netty-handler-4.1.73.Final.jar; 赠送原API文档:netty-handler-4.1.73.Final-javadoc.jar; 赠送源代码:netty-handler-4.1.73.Final-sources.jar; 赠送Maven依赖信息文件:netty-handler-4.1.73....

    android demo,使用Handler的postDelay,Runnable run实现延时3秒的splash。

    本示例中的“android demo”就是关于如何利用Handler的`postDelayed`方法和`Runnable`接口来实现一个延时3秒的Splash Screen。下面将详细解释这个过程以及涉及的技术点。 1. **Handler**: Handler是Android中处理...

    netty-handler-proxy-4.1.68.Final-API文档-中文版.zip

    赠送jar包:netty-handler-proxy-4.1.68.Final.jar; 赠送原API文档:netty-handler-proxy-4.1.68.Final-javadoc.jar; 赠送源代码:netty-handler-proxy-4.1.68.Final-sources.jar; 赠送Maven依赖信息文件:netty-...

    Handler与AsyncTask使用示例

    在Android开发中,`Handler`、`AsyncTask`和`Looper`是三个非常重要的概念,它们主要用于处理应用程序的异步操作和线程通信。本文将深入探讨这些知识点,并通过实例来展示它们如何协同工作。 首先,`Handler`是...

    Handlerjava代码实现

    在Android开发中,`Handler`是一个非常重要的组件,它用于处理UI线程之外的异步消息,实现线程间通信。`Handler`、`Looper`和`Message`三者共同构成了Android的消息处理机制,帮助开发者在不同的线程之间传递数据和...

    Handler 推荐用法 demo

    在Android开发中,`Handler`是一个至关重要的组件,主要用于处理线程间的通信,尤其是主线程(UI线程)与工作线程之间的交互。本`Handler`推荐用法的示例,旨在帮助开发者理解和掌握如何有效地使用`Handler`来管理...

    handler用法

    在Android开发中,Handler是一种非常重要的机制,它用于在主线程和子线程之间进行通信,处理异步消息。理解并熟练使用Handler是每个Android开发者必备的技能之一。本篇文章将详细讲解Handler的基本概念、工作原理...

    handler的简单示例

    在Android开发中,Handler是一种非常重要的机制,它用于在主线程中处理来自其他线程的消息,从而实现线程间通信,尤其是对UI的更新。在这个“handler的简单示例”中,我们将深入探讨Handler的工作原理及其在异步更新...

    android handler runnable使用实例(关键是内部run中停止)

    在Android应用开发中,Handler、Runnable和Looper是三个非常重要的组件,它们构成了Android的消息处理机制。这个机制使得UI线程可以非阻塞地处理来自其他线程的消息,从而避免了UI冻结,提升了用户体验。下面我们将...

    安卓handler的使用

    在Android应用开发中,Handler是一种重要的线程通信机制,它与Looper、Message紧密配合,用于在不同的线程间传递消息,解决多线程同步问题。本篇将详细讲解Handler的使用,包括如何创建Handler对象、如何发送和处理...

    详解Android中Handler的内部实现原理

    Handler是Android系统中用于线程间通信的关键组件,它的内部实现原理涉及到Thread、MessageQueue和Looper等核心类。首先,我们需要理解线程在操作系统中的基本概念,线程是程序执行的最小单位,每个线程都有自己的...

    Android应用程序消息处理机制(Looper、Handler)分析

    Android 应用程序中,消息处理机制是其异步编程的核心组成部分,主要涉及三个关键组件:Handler、Message和Looper。这种机制使得应用可以有效地管理线程间的通信,避免阻塞主线程,提升用户体验。 首先,我们需要...

    android 更新 UI 线程 handler

    为了解决这个问题,Android引入了Handler机制,配合Runnable对象来安全地在主线程中更新UI。以下将详细讲解这个过程。 首先,我们需要理解Android的线程模型。Android应用主要由主线程和工作线程组成。主线程负责...

Global site tag (gtag.js) - Google Analytics