文档章节

android中Handler的初步认识(一)

tiansl
 tiansl
发布于 2015/01/21 15:29
字数 1539
阅读 18
收藏 1

说实话,之前在java开发的时候,很少涉及多线程的东西。由于开发的项目体量比较小,技术也比较差,所以更多的考虑的是功能,很少对并发做优化

 

如今借着学习Android的机会,希望可以对多线程的知识有一个更好更全面地认识。哎,感觉自己技术基础还是太差,好好加油吧

 

首先,安卓使用的时单线程模型:

    当一个程序第一次启动时,Android会同时启动一个对应的主线程(Main Thread),主线程主要负责处理与UI相关的事件,如:用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。所以主线程通常又被叫做UI线程。

    在开发Android应用时必须遵守单线程模型的原则: Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。

           如果在非UI线程中直接操作UI线程,会抛出android.view.ViewRoot$CalledFromWrongThreadException:Only  the original thread that created a view hierarchy can touch itsviews,这与普通的java程序不同。

    由于UI线程负责事件的监听和绘图,因此,必须保证UI线程能够随时响应用户的需求,UI线程里的操作应该向中断事件那样短小,费时的操作(如网络连接)需要另开线程,否则,如果UI线程超过5s没有响应用户请求,会弹出对话框提醒用户终止应用程序。

    如果在新开的线程中需要对UI进行设定,就可能违反单线程模型,因此android采用一种复杂的Message Queue机制保证线程间通信。

    以上内容摘自 http://www.cnblogs.com/nio-nio/archive/2012/07/23/2604900.html,是我在网上看到的相 对比较容易理解的说明。读完以上这几段话之后,我对安卓单线程模式的理解:如果你要对UI进行操作那这些操作应该都放到主线程中;如果你要处理一些业务逻 辑或者其它的比较费时的操作,那就把这些操作放到子线程中。那因为大多数的UI更新都是基于业务逻辑的判断,如何让处理逻辑的子线程和处理UI的主线程通 信呢,这就需要用到Handler


Handler是干什么的: 


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

关于Handler的使用,我们首先来看一个简单例子:

        我们假设有这么一个需求:我们需要在程序中点击一个开始按钮,然后我们的程序会在后台启动一个定时任务(每隔一秒打印一个语句)。另外,我们还需要一个取消按钮,点击它终止后台的定时任务.

       我们先在界面中加入两个按钮,一个开始,一个取消。接下来是activity

 

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片

  1. package com.example.hander1;  

  2.   

  3. import java.util.Date;  

  4. import android.app.Activity;  

  5. import android.os.Bundle;  

  6. import android.os.Handler;  

  7. import android.util.Log;  

  8. import android.view.View;  

  9. import android.view.View.OnClickListener;  

  10. import android.widget.Button;  

  11.   

  12. public class MainActivity extends Activity {  

  13.   

  14.     Button startButton = null;  

  15.     Button stopButton = null;  

  16.     Handler handler = new Handler();  

  17.       

  18.     protected void onCreate(Bundle savedInstanceState) {  

  19.         super.onCreate(savedInstanceState);  

  20.         setContentView(R.layout.activity_main);  

  21.           

  22.         startButton = (Button) findViewById(R.id.startButton);  

  23.         stopButton = (Button) findViewById(R.id.stopButton);  

  24.           

  25.         //为button绑定onclicklistener  

  26.         startButton.setOnClickListener(new ButtonOnclikListener());  

  27.         stopButton.setOnClickListener(new ButtonOnclikListener());  

  28.     }  

  29.       

  30.     Runnable going = new Runnable() {     

  31.         @Override  

  32.         public void run() {  

  33.             //线程每次执行,打印日志  

  34.             Log.i("run", "going  "+new Date().getSeconds());  

  35.             //延时一秒钟后,再次将线程加入队列中  

  36.             handler.postDelayed(going, 1000);  

  37.         }  

  38.     };  

  39.   

  40.     class ButtonOnclikListener implements OnClickListener{  

  41.   

  42.         @Override  

  43.         public void onClick(View v) {     

  44.             switch(v.getId()){  

  45.             case R.id.startButton:  

  46.                 begin();  

  47.                 break;  

  48.             case R.id.stopButton:  

  49.                 stop();  

  50.                 break;  

  51.             default:  

  52.                 break;  

  53.             }  

  54.         }  

  55.           

  56.     }  

  57.       

  58.     //该方法将going添加到message queue中   

  59.     void begin(){  

  60.         handler.post(going);  

  61.     }  

  62.       

  63.     //从message queue中移除going  

  64.     void stop(){  

  65.         handler.removeCallbacks(going);  

  66.     }  

  67.   

  68. }  

 

下面是运行结果,程序启动后是这样

      当我点击启动按钮后,后台每秒中打印一条语句

     当我点击取消按钮后,后台不再打印语句

对于这个程序的运行过程我是这样理解的:

      1、当我点击启动按钮时:调用handler.post(going); 

handler的post方法说明是这样的:Causes the Runnable  r to be added to the message queue. The runnable will be run on the  thread to which this handler is attached.

         也就是说,当我调用了handler.post(going);这个方法之后,handler会将我实现的Runnable对象加入到message  queue中,系统会根据message  queue来执行。后面一句很重要,runnable会在当前handler所属的那个线程中执行,也就是说我的going会在程序的主线程中执行,而不 是新开启的其它线程。

·      2、在going的run方法中,我调用了handler.postDelayed(going, 1000);

     postDelayed这个方法和前面的post方法类似,只不过第二个参数的作用是让我的going延迟一秒钟执行。

     这样其实就形成了一个死循环(我没有规定跳出的条件),程序在我点击启动之后,每隔一秒钟会在message queue中加入执行going的内容。

3、当我点击取消按钮时:调用handler.removeCallbacks(going);

       虽在我在上面的写法中形成了一个死循环,但是我可以通过handler.removeCallbacks(going)这个方法,将message  queue这个队列中的going去掉,这样就不再执行going了。而且根据这个方法源码中的注释:Remove any pending posts  of Runnable r that are in the message queue. 应该是会把message  queue中所有未执行going全部去掉。

这个程序虽然很简单,但是我在一次看到的时候,仍然陷入了误区。由于没有仔细阅读 API,我刚开始以为handler.post()这个方法会新开启一个线程。后来看到API的时候才明白原来这个程序,只有一个主线程,只不过是通过 handler将实现的Runnable 对象加入到message queue中执行的。



本文转载自:http://blog.csdn.net/xiapinnong/article/details/22445973

tiansl

tiansl

粉丝 1
博文 17
码字总数 26152
作品 0
成都
私信 提问
HTC败诉或殃及其他Android手机制造商

新浪科技讯 北京时间7月17日下午消息,美国国际贸易委员会(以下简称“ITC”)周五做出一项初步判决,裁定HTC Android产品侵犯苹果两项专利。分析师认为,这项裁决或许会对其它Android设备制造...

红薯
2011/07/17
1K
6
Android 3即将发布 Google下周举办发布会

本周早些时候Google发布了Android 3.0蜂巢系统的预览版SDK软件开发工具包,让大家对这款新系统有一个初步的认识。为了让更多人对Android 3有更进一步的认识,Google计划在2月2日举办一次发布...

米狗族
2011/01/30
732
0
android应用开发简单理解

做了个应用,总结下对于android 应用的简单理解 从上图可以简单看出,主线程启动,这里把各种操作称为action,主要分为3部分: ui(视图绘制)、event(事件处理)和other(数据或网络等处理) 1.当...

blackylin
2013/06/18
649
2
Android手机Wi-Fi及 Wi-Fi直连

> Android WIFI: 当手机成功连接到Wi-Fi热点以后,手机所产生的上网流量都是通过Wi-Fi来传输的,而手机的移动流量会被禁用。但是,我们现在有特殊的业务需求,需要让手机成功连接Wi-Fi后还可...

desaco
03/13
0
0
深入理解Android消息处理系统——Looper、Handler、Thread

熟悉Windows编程的朋友可能知道Windows程序是消息驱动的,并且有全局的消息循环系统。而Android应用程序也是消息驱动的,按道理来说也应该提供消息循环机制。实际上谷歌参考了Windows的消息循...

惊天
2011/07/26
726
0

没有更多内容

加载失败,请刷新页面

加载更多

关于AsyncTask的onPostExcute方法是否会在Activity重建过程中调用的问题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/XG1057415595/article/details/86774575 假设下面一种情况...

shzwork
今天
6
0
object 类中有哪些方法?

getClass(): 获取运行时类的对象 equals():判断其他对象是否与此对象相等 hashcode():返回该对象的哈希码值 toString():返回该对象的字符串表示 clone(): 创建并返此对象的一个副本 wait...

happywe
今天
6
0
Docker容器实战(七) - 容器中进程视野下的文件系统

前两文中,讲了Linux容器最基础的两种技术 Namespace 作用是“隔离”,它让应用进程只能看到该Namespace内的“世界” Cgroups 作用是“限制”,它给这个“世界”围上了一圈看不见的墙 这么一...

JavaEdge
今天
8
0
文件访问和共享的方法介绍

在上一篇文章中,你了解到文件有三个不同的权限集。拥有该文件的用户有一个集合,拥有该文件的组的成员有一个集合,然后最终一个集合适用于其他所有人。在长列表(ls -l)中这些权限使用符号...

老孟的Linux私房菜
今天
7
0
面试套路题目

作者:抱紧超越小姐姐 链接:https://www.nowcoder.com/discuss/309292?type=3 来源:牛客网 面试时候的潜台词 抱紧超越小姐姐 编辑于 2019-10-15 16:14:56APP内打开赞 3 | 收藏 4 | 回复24 ...

MtrS
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部