在多线程编程的时候,我们经常会用到Handler,Thread和Runnable这三个类,我们来看看这三个类之间是怎么样的关系?

  首先说明Android的CPU分配的最小单元是线程,Handler一般是在某个线程里创建的,因而Handler和Thread就是相互绑定的,一一对应。

而Runnable是一个接口,Thread是Runnable的子类。可以说,他俩都算一个进程。 HandlerThread顾名思义就是可以处理消息循环的线程,他是一个拥有Looper的线程,可以处理消息循环。

与其说Handler和一个线程绑定,不如说Handler是和Looper一一对应的。

最后需要说明的是,在UI线程(主线程)中:

  mHandler=new Handler();

     mHandler.post(new Runnable(){

     void run(){

        //在run方法里执行代码...
}
});

 这个线程其实是在UI线程之内运行的,并没有新建线程。

常见的新建线程的方法是:

   Thread thread = new Thread();

     thread.start();

     HandlerThread thread = new HandlerThread("string");

     thread.start();

Android中Handler的使用方法——构建定时器 收藏

◆ 在代码中定义一个整形常量,代表消息的ID。此处不妨对其取名为TIMERID。

◆创建自己的Handler,在该Handler中HandlerMessage处理函数中。在消息处理函数中,我们首先发送消息TIMERID,并指定其延迟的时间,单位为毫秒。然后可以调用相应的事务处理函数。需要注意的是,如果事件处理函数花费的时间过长,则下次消息到来时,会导致不能及时处理。

◆创建startTimer函数,在该函数中触发定时器,实际上就是发送一个TIMERID消息,来第一次触发消息。

◆创建stopTimer函数,在该函数中停止定时器,实际上就是把TIMERID的消息从消息队列中删除即可。

下面让我们来以代码作为说明。

 package com.android.mytimer; 

 import android.os.Handler; 

 import android.os.Message; 

 public class MyTimer extends Handler { 

         private static int TIMERID = 0; //静态变量,保证ID唯一。当ID超过整形最大值时,应该把它恢复为0 

         private final int mInterval; 

         public interface CallBack{ 

             void timerCallBack(); 

         }

         private CallBack mCallBack;

         public MyTimer(int interval, CallBack callback) 

         { 

             mInterval = interval; 

             mCallBack = callback; 

             TIMERID++; 

         }

         @Override 

         public void handleMessage(Message msg) { 

             // TODO Auto-generated method stub 

             super.handleMessage(msg); 

             if( msg.what == TIMERID) 

             {
Message message = obtainMessage(TIMERID); this.sendMessageDelayed(message, mInterval); //for speed up, NO NULL Pointer exception check mCallBack.timerCallBack();
}
} public void startTimer() {
Message msg = this.obtainMessage(TIMERID); this.sendMessage(msg); } public void stopTimer() { this.removeMessages(TIMERID); }
}

其中接口CallBack是一个回调函数,使用这个定时器的应用必须实现该接口,并且在构造函数当中传入该类。如下

 public class TestTimer implement MyTImer.CallBack{

         MyTimer mTimer;

         public TestTimer()

         {

             mTimer = new MyTImer(10, this);

             mTimer.start();

         }

         void timerCallBack();

         {

             Log.i("TestTimer", "this is the timerCallBack");

         }

 }

一> Handler的定义:

主要接受子线程发送的数据, 并用此数据配合主线程更新UI.

解释: 当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,进行事件分发, 比如说, 你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作。  如果此时需要一个耗时的操作,例如: 联网读取数据,    或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,,如果你放在主线程中的话,界面会出现假死现象, 如果5秒钟还没有完成的话,,会收到Android系统的一个错误提示  "强制关闭".  这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,,Android主线程是线程不安全的,也就是说,更新UI只能在主线程中更新,子线程中操作是危险的. 这个时候,Handler就出现了.,来解决这个复杂的问题 ,    由于Handler运行在主线程中(UI线程中),  它与子线程可以通过Message对象来传递数据, 这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据)  , 把这些消息放入主线程队列中,配合主线程进行更新UI。(文/springhi-2009)

<二> Handler一些特点

handler可以分发Message对象和Runnable对象到主线程中, 每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程),
        它有两个作用: (1):  安排消息或Runnable 在某个主线程中某个地方执行, (2)安排一个动作在不同的线程中执行
      
        Handler中分发消息的一些方法
        post(Runnable)
        postAtTime(Runnable,long)
        postDelayed(Runnable long)
        sendEmptyMessage(int)
        sendMessage(Message)
        sendMessageAtTime(Message,long)
        sendMessageDelayed(Message,long)

以上post类方法允许你排列一个Runnable对象到主线程队列中,
        sendMessage类方法, 允许你安排一个带数据的Message对象到队列中,等待更新.

<三> Handler实例

(1) 子类需要继承Hendler类,并重写handleMessage(Message msg) 方法, 用于接受线程数据

以下为一个实例,它实现的功能为 : 通过线程修改界面Button的内容

 public class MyHandlerActivity extends Activity {

     Button button;

      MyHandler myHandler;

     protected void onCreate(Bundle savedInstanceState) {

          super.onCreate(savedInstanceState);

          setContentView(R.layout.handlertest);

          button = (Button) findViewById(R.id.button);

          myHandler = new MyHandler();

          // 当创建一个新的Handler实例时, 它会绑定到当前线程和消息的队列中,开始分发数据 

          // Handler有两个作用, (1) : 定时执行Message和Runnalbe 对象

          // (2): 让一个动作,在不同的线程中执行.

          // 它安排消息,用以下方法

          // post(Runnable)

          // postAtTime(Runnable,long)

          // postDelayed(Runnable,long)

          // sendEmptyMessage(int)

          // sendMessage(Message); 

          // sendMessageAtTime(Message,long)

          // sendMessageDelayed(Message,long)

          // 以上方法以 post开头的允许你处理Runnable对象

          //sendMessage()允许你处理Message对象(Message里可以包含数据,)

          MyThread m = new MyThread();

          new Thread(m).start();

      }

      /**

       * 接受消息,处理消息 ,此Handler会与当前主线程一块运行

       * */

      class MyHandler extends Handler {

          public MyHandler() {

          }

          public MyHandler(Looper L) {

              super(L);

          }

          // 子类必须重写此方法,接受数据

         @Override
public void handleMessage(Message msg) { // TODO Auto-generated method stub Log.d("MyHandler", "handleMessage......"); super.handleMessage(msg); // 此处可以更新UI Bundle b = msg.getData(); String color = b.getString("color"); MyHandlerActivity.this.button.append(color); } } class MyThread implements Runnable { public void run() { try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } Log.d("thread.......", "mThread........"); Message msg = new Message(); Bundle b = new Bundle();// 存放数据 b.putString("color", "我的"); msg.setData(b); MyHandlerActivity.this.myHandler.sendMessage(msg); // 向Handler发送消息,更新UI } } }

Android中Handler 、Thread和Runnable之间的关系的更多相关文章

  1. Android 中Activity,Window和View之间的关系

    转自:http://hi.baidu.com/xiaofanqing/blog/item/8261ac114ab14f64cb80c435.html 我这里根据我个人的理解来讲讲我个人对这3个概念的理 ...

  2. Android中Bitmap, Drawable, Byte,ID之间的转化

    Android中Bitmap, Drawable, Byte,ID之间的转化 1.  Bitmap 转化为 byte ByteArrayOutputStream out = new ByteArray ...

  3. 【转】Android中dip(dp)与px之间单位转换

    Android中dip(dp)与px之间单位转换 dp这个单位可能对web开发的人比较陌生,因为一般都是使用px(像素)但是,现在在开始android应用和游戏后,基本上都转换成用dp作用为单位了,因 ...

  4. 在android中实现webview与javascript之间的交互(转)

    参见“在android中实现webview与javascript之间的交互”

  5. android开发 系统时间与定时器之间有关系嘛?

    如题: android开发 系统时间与定时器之间有关系嘛? 答案:有. 看定时器源码: /* * Schedule a task. */ private void scheduleImpl(Timer ...

  6. Android中Handler使用浅析

    1. Handler使用引出 现在作为客户,有这样一个需求,当打开Activity界面时,开始倒计时,倒计时结束后跳转新的界面(思维活跃的朋友可能立马想到如果打开后自动倒计时,就类似于各个APP的欢迎 ...

  7. Android中Handler的消息处理机制以及源码分析

    在实际项目当中,一个很常见的需求场景就是在根据子线程当中的数据去更新ui.我们知道,android中ui是单线程模型的,就是只能在UI线程(也称为主线程)中更新ui.而一些耗时操作,比如数据库,网络请 ...

  8. Android 中 Handler 引起的内存泄露

    在Android常用编程中,Handler在进行异步操作并处理返回结果时经常被使用.其实这可能导致内存泄露,代码中哪里可能导致内存泄露,又是如何导致内存泄露的呢?那我们就慢慢分析一下.http://w ...

  9. android中handler用法总结

    一.Handler的定义: Handler主要接收子线程发送的数据, 并用此数据配合主线程更新UI,用来跟UI主线程交互用.比如可以用handler发送一个message,然后在handler的线程中 ...

随机推荐

  1. MySQL root密码找回

    以MySQL多实例为例,演示找回MySQL root的密码 1.关闭mysql服务 [root@mysql ~]# mysqladmin -uroot -poldboy123 -S /data/330 ...

  2. hdu4578 Transformation

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4578 题目大意:n个数(初始为0)m个操作,操作类型有4种,操作1把区间的每个数+a,操作2把区间的每 ...

  3. HDU2063 过山车

    过山车 RPG girls今天和大家一起去游乐场玩,终于可以坐上梦寐以求的过山车了.可是,过山车的每一排只有两个座位,而且还有条不成文的规矩,就是每个女生必须找个个男生做partner和她同坐.但是, ...

  4. PTA Iterative Mergesort

    How would you implement mergesort without using recursion? The idea of iterative mergesort is to sta ...

  5. iOS Core Animation之CALayer心得

    使用CALayer的mask实现注水动画效果 Core Animation一直是iOS比较有意思的一个主题,使用Core Animation可以实现非常平滑的炫酷动画.Core animtion的AP ...

  6. 通过jQuery Ajax使用FormData对象上传文件

    FormData对象,是可以使用一系列的键值对来模拟一个完整的表单,然后使用XMLHttpRequest发送这个"表单". 在 Mozilla Developer 网站 使用For ...

  7. C#对于文件操作

    //C#追加文件 StreamWriter sw = File.AppendText(Server.MapPath(".")+"\\myText.txt"); ...

  8. Coursera Machine Learning 作业答案脚本 分享在github上

    Github地址:https://github.com/edward0130/Coursera-ML

  9. 苗子sale record

    2016年7月11日 橘白/阳光 发广州 220  中通 719373064939 成功2016年7月11日 横纹RA    发潮州 250  中通 719373064940 成功2016年7月18日 ...

  10. Jquery动态在td中添加checkbox

    如图:想要在这个id为headId的<td>中,用jquery动态添加checkbox 代码如下 : data是我用ajax 从后台获取的数据,里面含有若干个user类,我想把所有的人名字 ...