观点一:

Android 对进程的重要性评级的时候,选取它最高的级别。另外,当被另外的一个进程依赖的时候,某个进程的级别可能会增高。一个为其他进程服务的进程永远不会比被服务的进程重要级低。因为服务进程比后台activity进程重要级高,因此一个要进行耗时工作的activity最好启动一个service来做这个工作,而不是开启一个子进程――特别是这个操作需要的时间比activity存在的时间还要长的时候。例如,在后台播放音乐,向网上上传摄像头拍到的图片,使用service可以使进程最少获取到“服务进程”级别的重要级,而不用考虑activity目前是什么状态。broadcast receivers做费时的工作的时候,也应该启用一个服务而不是开一个线程。

观点二:

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

观点三:

为了避免拖住GUI,一些较费时的对象应该交给独立的线程去执行。如果幕后的线程来执行UI对象,Android就会发出错误讯息 CalledFromWrongThreadException

观点四:Handler

  handler可以分发Message对象和Runnable对象到主线程中。

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

观点五: Message Queue

Message Queue消息队列,用来存放通过Handler发布的消息,按照先进先出执行。
每个message queue都会有一个对应的Handler。Handler会向message queue通过两种方法发送消息:sendMessage或post。这两种消息都会插在message queue队尾并按先进先出执行。但通过这两种方法发送的消息执行的方式略有不同:通过sendMessage发送的是一个message对象,会被Handler的handleMessage()函数处理;而通过post方法发送的是一个runnable对象,则会自己执行。

观点六: Looper是每条线程里的Message Queue的管家。

Android没有Global的Message Queue,而Android会自动替主线程(UI线程)建立Message Queue,但在子线程里并没有建立Message Queue。所以调用Looper.getMainLooper()得到的主线程的Looper不为NULL,但调用Looper.myLooper()得到当前线程的Looper就有可能为NULL。

对于子线程使用Looper,API Doc提供了正确的使用方法:

  1. class LooperThread extends Thread {
  2. public Handler mHandler;
  3. public void run() {
  4. Looper.prepare(); //创建本线程的Looper并创建一个MessageQueue
  5. mHandler = new Handler() {
  6. public void handleMessage(Message msg) {
  7. // process incoming messages here
  8. }
  9. };
  10. Looper.loop(); //开始运行Looper,监听Message Queue
  11. }
  12. }

主要转自http://android.blog.51cto.com/268543/343823/

一个异步加载listview的例子,用2种方法:

在网上有很多文章讲述主线程和其他子线程如何交互,传送信息,最终谁来执行处理信息之类的,个人理解是最简单的方法——判断Handler对象里面的Looper对象是属于哪条线程的,则由该线程来执行!
    1. 当Handler对象的构造函数的参数为空,则为当前所在线程的Looper;
    2. Looper.getMainLooper()得到的是主线程的Looper对象,Looper.myLooper()得到的是当前线程的Looper对象。

现在来看一个例子,模拟从网络获取数据,加载到ListView的过程:

  1. public class ListProgressDemo extends ListActivity {
  2. @Override
  3. public void onCreate(Bundle savedInstanceState) {
  4. super.onCreate(savedInstanceState);
  5. setContentView(R.layout.listprogress);
  6. ((Button) findViewById(R.id.load_Handler)).setOnClickListener(new View.OnClickListener(){
  7. @Override
  8. public void onClick(View view) {
  9. data = null;
  10. data = new ArrayList<String>();
  11. adapter = null;
  12. showDialog(PROGRESS_DIALOG);
  13. new ProgressThread(handler, data).start();
  14. }
  15. });
  16. }
  17. @Override
  18. protected Dialog onCreateDialog(int id) {
  19. switch(id) {
  20. case PROGRESS_DIALOG:
  21. return ProgressDialog.show(this, "",
  22. "Loading. Please wait...", true);
  23. default: return null;
  24. }
  25. }
  26. private class ProgressThread extends Thread {
  27. private Handler handler;
  28. private ArrayList<String> data;
  29. public ProgressThread(Handler handler, ArrayList<String> data) {
  30. this.handler = handler;
  31. this.data = data;
  32. }
  33. @Override
  34. public void run() {
  35. for (int i=0; i<8; i++) {
  36. data.add("ListItem"); //后台数据处理
  37. try {
  38. Thread.sleep(100);
  39. }catch(InterruptedException e) {
  40. Message msg = handler.obtainMessage();
  41. Bundle b = new Bundle();
  42. b.putInt("state", STATE_ERROR);
  43. msg.setData(b);
  44. handler.sendMessage(msg);
  45. }
  46. }
  47. Message msg = handler.obtainMessage();
  48. Bundle b = new Bundle();
  49. b.putInt("state", STATE_FINISH);
  50. msg.setData(b);
  51. handler.sendMessage(msg);
  52. }
  53. }
  54. // 此处甚至可以不需要设置Looper,因为Handler默认就使用当前线程的Looper
  55. private final Handler handler = new Handler(Looper.getMainLooper()) {
  56. public void handleMessage(Message msg) { // 处理Message,更新ListView
  57. int state = msg.getData().getInt("state");
  58. switch(state){
  59. case STATE_FINISH:
  60. dismissDialog(PROGRESS_DIALOG);
  61. Toast.makeText(getApplicationContext(),
  62. "加载完成!",
  63. Toast.LENGTH_LONG)
  64. .show();
  65. adapter = new ArrayAdapter<String>(getApplicationContext(),
  66. android.R.layout.simple_list_item_1,
  67. data );
  68. setListAdapter(adapter);
  69. break;
  70. case STATE_ERROR:
  71. dismissDialog(PROGRESS_DIALOG);
  72. Toast.makeText(getApplicationContext(),
  73. "处理过程发生错误!",
  74. Toast.LENGTH_LONG)
  75. .show();
  76. adapter = new ArrayAdapter<String>(getApplicationContext(),
  77. android.R.layout.simple_list_item_1,
  78. data );
  79. setListAdapter(adapter);
  80. break;
  81. default:
  82. }
  83. }
  84. };
  85. private ArrayAdapter<String> adapter;
  86. private ArrayList<String> data;
  87. private static final int PROGRESS_DIALOG = 1;
  88. private static final int STATE_FINISH = 1;
  89. private static final int STATE_ERROR = -1;
  90. }

这个例子,我自己写完后觉得还是有点乱,要稍微整理才能看明白线程间交互的过程以及数据的前后变化。随后了解到AsyncTask类,相应修改后就很容易明白了!

2.3 AsyncTask

AsyncTask版:
  1. ((Button) findViewById(R.id.load_AsyncTask)).setOnClickListener(new View.OnClickListener(){
  2. @Override
  3. public void onClick(View view) {
  4. data = null;
  5. data = new ArrayList<String>();
  6. adapter = null;
  7. //显示ProgressDialog放到AsyncTask.onPreExecute()里
  8. //showDialog(PROGRESS_DIALOG);
  9. new ProgressTask().execute(data);
  10. }
  11. });
  12. private class ProgressTask extends AsyncTask<ArrayList<String>, Void, Integer> {
  13. /* 该方法将在执行实际的后台操作前被UI thread调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条。*/
  14. @Override
  15. protected void onPreExecute() {
  16. // 先显示ProgressDialog
  17. showDialog(PROGRESS_DIALOG);
  18. }
  19. /* 执行那些很耗时的后台计算工作。可以调用publishProgress方法来更新实时的任务进度。 */
  20. @Override
  21. protected Integer doInBackground=\'#\'" /span>
  22. ArrayList<String> data = datas[0];
  23. for (int i=0; i<8; i++) {
  24. data.add("ListItem");
  25. }
  26. return STATE_FINISH;
  27. }
  28. /* 在doInBackground 执行完成后,onPostExecute 方法将被UI thread调用,
  29. * 后台的计算结果将通过该方法传递到UI thread.
  30. */
  31. @Override
  32. protected void onPostExecute(Integer result) {
  33. int state = result.intValue();
  34. switch(state){
  35. case STATE_FINISH:
  36. dismissDialog(PROGRESS_DIALOG);
  37. Toast.makeText(getApplicationContext(),
  38. "加载完成!",
  39. Toast.LENGTH_LONG)
  40. .show();
  41. adapter = new ArrayAdapter<String>(getApplicationContext(),
  42. android.R.layout.simple_list_item_1,
  43. data );
  44. setListAdapter(adapter);
  45. break;
  46. case STATE_ERROR:
  47. dismissDialog(PROGRESS_DIALOG);
  48. Toast.makeText(getApplicationContext(),
  49. "处理过程发生错误!",
  50. Toast.LENGTH_LONG)
  51. .show();
  52. adapter = new ArrayAdapter<String>(getApplicationContext(),
  53. android.R.layout.simple_list_item_1,
  54. data );
  55. setListAdapter(adapter);
  56. break;
  57. default:
  58. }
  59. }

Android另外提供了一个工具类:AsyncTask。它使得UI thread的使用变得异常简单。它使创建需要与用户界面交互的长时间运行的任务变得更简单,不需要借助线程和Handler即可实现。

1)  子类化AsyncTask
2)  实现AsyncTask中定义的下面一个或几个方法

onPreExecute() 开始执行前的准备工作;
doInBackground=\'#\'" ) 开始执行后台处理,可以调用publishProgress方法来更新实时的任务进度;
onProgressUpdate(Progress...)  在publishProgress方法被调用后,UI thread将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。
onPostExecute(Result) 执行完成后的操作,传送结果给UI 线程。
这4个方法都不能手动调用。而且除了doInBackground=\'#\'" /div>

1) AsyncTask的实例必须在UI thread中创建;
2) AsyncTask.execute方法必须在UI thread中调用;
同时要注意:该task只能被执行一次,否则多次调用时将会出现异常。而且是不能手动停止的,这一点要注意,看是否符合你的需求!
在使用过程中,发现AsyncTask的构造函数的参数设置需要看明白:AsyncTask<Params, Progress, Result>
Params对应doInBackground=\'#\'" AsyncTask().execute(Params... params),就是传进来的Params数据,你可以execute(data)来传送一个数据,或者execute(data1, data2, data3)这样多个数据。
Progress对应onProgressUpdate(Progress...)的参数类型;
Result对应onPostExecute(Result)的参数类型。
当以上的参数类型都不需要指明某个时,则使用Void,注意不是void。不明白的可以参考上面的例子,或者API Doc里面的例子。

转载于:https://www.cnblogs.com/linxiaojiang/archive/2013/04/23/3036924.html

handler 与message的一些理解相关推荐

  1. 深入理解Handler、Message、MessageQueue、Looper

    本文是从源码的角度对andorid异步消息处理机制的梳理,那么在文章开始阶段,先简单介绍,异步消息处理机制中各部件的作用以及处理处理机制的概述 1.Handler.Message.MessageQue ...

  2. Android的消息处理机制——Looper,Handler和Message浅析

    题外话: 说来有些惭愧,对于这三者的初步认识居然是在背面试题的时候.那个时候自己接触Android的时间还不长,学习的书籍也就是比较适合入门的<疯狂Android讲义>,当然在学到Hand ...

  3. Message、Handler、Message Queue、Looper、Thread之间的关系(未完成)

    1. 请解释下在单线程模型中Message.Handler.Message Queue.Looper.Thread之间的关系 2. 什么是IntentService?有何优点? 1) 它是对单线程消息 ...

  4. 【Android 异步操作】手写 Handler ( 总结 | Message | MessageQueue | Looper | Handler ) ★

    文章目录 一.Message 消息 二.Handler 消息处理者 三.MessageQueue 消息队列 四.Looper 循环者 五.关于 Looper 线程本地变量的说明 一.Message 消 ...

  5. Android基础架构:Native层 Looper、Handler、Message 研究

    Android基础架构:Native层 Looper.Handler.Message 研究1,参考: https://www.cnblogs.com/roger-yu/p/15099541.html ...

  6. 安卓多线程编程系列3:使用handler和message下载网络图片

    使用handler和message进行网络操作是多线程编程经常使用的形式,下面我们来一起看一下它的使用方法. 整体思路:触发一个事件,在这个事件中开启一个线程,在这个线程中定义消息,在消息中携带数据, ...

  7. Handler.obtainMessage()的认识和理解

    转自:http://www.cnblogs.com/android007/archive/2012/05/10/2494766.html 话说在工作中第一次接触Android 的Handler 的时候 ...

  8. Handler消息Message屏障消息

    Message分为3中:普通消息(同步消息).屏障消息(同步屏障)和异步消息.我们通常使用的都是普通消息,而屏障消息就是在消息队列中插入一个屏障(也是一个消息,这个消息会保存到当前Hanlder中,直 ...

  9. Android异步消息处理机制 深入理解Looper、Handler、Message三者关系

    转载子:http://blog.csdn.net/lmj623565791/article/details/38377229 ,本文出自[张鸿洋的博客] 很多人面试肯定都被问到过,请问Android中 ...

最新文章

  1. 叶杰平:主流强化学习过分简化假设,与真实场景差距较大
  2. android数据存放map_android - Java后台把数据用json发到手机端,里面是map存放的,必须要说明数据的类型?...
  3. 关于wordpress 点击文章查看内容跳转加载失败(404)的解决方法
  4. 牛客网【每日一题】 合集
  5. 冒泡和快速排序的时间复杂度_三分钟快速记住冒泡排序算法
  6. 云场景实践研究第37期:悦跑圈
  7. memcpy()和memmove()函数之间区别
  8. 点播的时候出现 “S1-10921” 的错误
  9. 机器学习系列手记(六):概率图模型之概率图模型的联合概率分布
  10. 业务太忙,真的是没时间搞自动化理由吗?
  11. Oracle Database Link基础
  12. 中小板企业上市要走哪些流程
  13. Long-tail Relation Extraction via Knowledge Graph Embeddings and Graph Convolution Networks
  14. 照片调色系列教程(11):浪漫色调 温情暖暖
  15. pc_lint的用法转
  16. python中字典的循环遍历的方式
  17. 《把时间当作朋友》---- 读书笔记
  18. 百度图库已上传的图片名字怎么修改命名?
  19. 【成像】【8】太赫兹光学——波束耦合,高阶高斯波束模型
  20. 爬取google scholar数据

热门文章

  1. 过去几年接触了很多小公司小品牌
  2. 有哪些类目适合刚创业的新手淘宝卖家做?
  3. 如果身价千万,你还会事无巨细亲力亲为吗
  4. 布尔运算,二进制和门电路
  5. 腾讯不允许将会员借给别人用,大家怎么看?
  6. We want to do better without being distracted
  7. go使用redis——redigo使用HMSET存储结构体
  8. 配置docker阿里云镜像加速
  9. 印象笔记添加txt附件
  10. ubuntu15.04在安装完vmware11后打开提示 VMware Kernel Module Updater