android的Handler

前言

学习android一段时间了,为了进一步了解android的应用是如何设计开发的,决定详细研究几个开源的android应用。从一些开源应用中吸收点东西,一边进行量的积累,一边探索android的学习研究方向。这里我首先选择了jwood的Standup Timer 项目。本文将把研究的内容笔记整理,建立一个索引列表。

关键词

Android.os.Handler涉及较多的知识点,我把一些关键词列举在下面,将主要介绍Handler:
  •   android.os.Handler 、 android.os.Handler.Callback
  •   Looper、
  •   Threadle、Runnable
  •   Message、Message queue

android.os.Handler

Handler在android里负责发送和处理消息。它的主要用途有:
1)按计划发送消息或执行某个Runnanble(使用POST方法);
2)从其他线程中发送来的消息放入消息队列中,避免线程冲突(常见于更新UI线程)
默认情况下,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)。

倒计时程序

利用Timer 编写一个倒计时程序,程序使用Timer和TimerTask来完成倒计时,同时使用sendMessages方法发送消息,然后在HanleMessage里更新UI。
Activity布局:

<?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:layout_gravity="center"
android:id="@+id/txt"
/>
<Button
android:id="@+id/btnStartTime"
android:text="开始计时"
android:layout_width="80dip"
android:layout_height="wrap_content"

></Button>
<Button
android:id="@+id/btnStopTime"
android:text="停止计时"
android:layout_width="80dip"
android:layout_height="wrap_content"
/>

<SeekBar android:id="@+id/SeekBar01" android:layout_width="match_parent" android:layout_height="wrap_content"></SeekBar>
</LinearLayout>

这里使用TextView 来显示倒计时的时间变化,两个按钮用于控制时间的开始和停止。SeekBar主要是用于查看线程是否被阻塞(阻塞时无法拖动)。

@Override
publicvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txt = (TextView) findViewById(R.id.txt);
btnStart = (Button) findViewById(R.id.btnStartTime);
btnStop = (Button) findViewById(R.id.btnStopTime);
Log.d("ThreadId", "onCread:"
+ String.valueOf(Thread.currentThread().getId()));
myHandler =new Handler(this);

btnStart.setOnClickListener(this);
btnStop.setOnClickListener(this);

}

在onCreate方法中初始化元素个元素,myHandler = new Handler(this); 调用的是  Handler(Handler.Callback callback)构造函数,在回调方法callback中对发送来的消息进行处理(这样我们就不必使用内部类的写法来 重写HandleMessage()方法了),因此Activity必须实现android.os.Handler.Callback 接口。我们还在将onCreate 方法的ThreadId 记录在了Log中用以和消息发送、处理时所作的线程进行比较。


@Override
publicvoid onClick(View v) {
switch (v.getId()) {
case R.id.btnStartTime:
startTimer();
break;
case R.id.btnStopTime:
timer.cancel();

break;
}

}

privatesynchronizedvoid startTimer() {

timer =new Timer();
// TimerTask updateTimerValuesTask = new TimerTask() {
// @Override
// public void run() {
// updateTimerValues();
// }
//
// };
//自定义的CallBack模式。Task继承自TimerTask
Task updateTimerValuesTask =new Task(this);

timer.schedule(updateTimerValuesTask, 1000, 1000);
}

//执行耗时的倒计时任务。
privatevoid updateTimerValues() {
total--;

Log.d("ThreadId", "send:"
+ String.valueOf(Thread.currentThread().getId()));

Message msg=new Message();
Bundle date =new Bundle();// 存放数据
date.putInt("time", total);
msg.setData(date);
msg.what=0;
myHandler.sendMessage(msg);

//另一种写法
// Message msg=myHandler.obtainMessage();
// Bundle date = new Bundle();// 存放数据
// date.putInt("time", total);
// msg.setData(date);
// msg.what=0;
// msg.sendToTarget();

}

@Override
publicvoid TaskRun() {
updateTimerValues();

}

实现Button按钮的事件处理以此进入倒计时操作。这里使用的Timer 来执行定时操作(其实我们完全可以另起一个线程)。Task类继承了TimerTask类,里面增加了一个任务处理接口来实现回调模式,应此Activity需要实现该回调的接口 ITaskCallBack(这样做是因为我比较不喜欢内部类的编写方法)。

publicinterface ITaskCallBack {

void TaskRun();
}

publicclass Task extends TimerTask {

private ITaskCallBack iTask;

public Task(ITaskCallBack iTaskCallBack)
{
super();
iTask=iTaskCallBack;
}

publicvoid setCallBack(ITaskCallBack iTaskCallBack)
{
iTask=iTaskCallBack;
}
@Override
publicvoid run() {
// TODO Auto-generated method stub
iTask.TaskRun();
}

}

这是Java的回调函数的一般写法。

实现CallBack
可以看到 实现android.os.Handler.Callback 接口,其实就是对handleMessage()方法进行重写(和内部类的一个区别是,内部类的返回值是Void)。

运行结果

可以看到在onCreate 方法中线程的ID是1(UI线程) 这与 HandlerMessage 进行消息处理时是所作的线程ID是一样的,而消息发送的线程ID则为8非UI线程。

使用Threadle进行实现


publicclass ThreadHandlerrActivity extends Activity implements Callback,
OnClickListener {

private TextView txt;
private Button btnStart, btnStop;
private Handler myHandler;
private TimerThread timerThread;
privateint Total=30;

/** Called when the activity is first created. */
@Override
publicvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txt = (TextView) findViewById(R.id.txt);
btnStart = (Button) findViewById(R.id.btnStartTime);
btnStop = (Button) findViewById(R.id.btnStopTime);
Log.d("ThreadId", "onCread:"
+ String.valueOf(Thread.currentThread().getId()));
myHandler =new Handler(this);

btnStart.setOnClickListener(this);
btnStop.setOnClickListener(this);

}

/**
* 实现消息处理
*/
@Override
publicboolean handleMessage(Message msg) {

switch(msg.what)
{
case0:
Bundle date=msg.getData();
txt.setText(String.valueOf(date.getInt("time")));

Log.d("ThreadId", "HandlerMessage:"
+ String.valueOf(Thread.currentThread().getId()));
Log.d("ThreadId", "msgDate:"
+ String.valueOf(date.getInt("time")));
break;

}
returnfalse;
}

@Override
publicvoid onClick(View v) {
switch (v.getId()) {
case R.id.btnStartTime:
//自定义的线程
timerThread=new TimerThread(myHandler,60);
timerThread.start();

break;
case R.id.btnStopTime:
timerThread.stop();
//timerThread.destroy();
break;
}

}

}

自定义的线程类

这里继承了Thread类,也可以直接实现 Runnable接口。

关于POST

Post的各种方法是把一个Runnable发送给消息队列,它将在到达时进行处理。
POST

使用POST的方式 是将Runnable 一起发送给处理的线程(这里为UI),如果Runnable的操作比较耗时的话那线程将进入阻塞状态。可以看到先运行 Runnable的Run方法 然后在进入 HandleMessage() 。我还尝试了另一种写法,将TimerThreadPOST过去,运行结果是一样的。

代码

可以说POST的各种方法主要是用于 “按计划发送消息或执行某个Runnanble(使用POST方法)”。

参考文献

android学习笔记之消息机制,异步和多线程
android handler概念解释
SDK

android的Handler相关推荐

  1. android asynctask源码分析,Android通过Handler与AsyncTask两种方式动态更新ListView(附源码)...

    本文实例讲述了Android通过Handler与AsyncTask两种方式动态更新ListView的方法.分享给大家供大家参考,具体如下: 有时候我们需要修改已经生成的列表,添加或者修改数据,noti ...

  2. Android中Handler

    本文通过例子来验证和说明使用Handler对象开启的线程是否和主线程为在同一线程中. 程序结构图如下: [1] HandlerActivity.java中的源码如下: [html] view plai ...

  3. (转)Android笔记--handler机制

    一.重要参考资料 [参考资料] 目前来看,下面的几个网址中的内容质量比较不错,基本不需要再读别的网址了. 1.android消息机制一 http://xtfncel.javaeye.com/blog/ ...

  4. Android中Handler的使用

    在Android开发中,我们常常会遇到这样一种情况:在UI界面上进行某项操作后要运行一段非常耗时的代码,比方我们在界面上点击了一个"下载"button,那么我们须要运行网络请求,这 ...

  5. Android使用Handler造成内存泄露的分析及解决方法

    Android使用Handler造成内存泄露的分析及解决方法 参考文章: (1)Android使用Handler造成内存泄露的分析及解决方法 (2)https://www.cnblogs.com/xu ...

  6. 【Android】Handler 机制 ( Handler | Message | Looper | MessageQueue )

    文章目录 I . Handler 机制简介 II . Handler 机制 Handler Message Looper MessageQueue 四组件对应关系 III . Handler ( 消息 ...

  7. Android中Handler消息传递机制应用之子线程不允许操作主线程的组件

    场景 进程 一个Android应用就是一个一个进程,每个应用在各自的进程中运行. 线程 比进程更小的独立运行的基本单位,一个进程可以包含多个线程. 要求 一个TextView和一个Button,点击B ...

  8. android内部通信handler

    什么是handler? handler主要用在用户同自己创建的线程进行通信,andorid应用程序在主线程中会维护一个消息队列,通过Message对象在线程间进行通信.在handler内部的handl ...

  9. Android之Handler探索

    Handler背景理解: Handler被最多的使用在了更新UI线程中,但是,这个方法具体是什么样的呢?我在这篇博文中先领着大家认识一下什么是handler以及它是怎么样使用在程序中,起着什么样的作用 ...

  10. Android之Handler用法总结(1)

    方法一:(java习惯,在android平台开发时这样是不行的,因为它违背了单线程模型) 刚刚开始接触android线程编程的时候,习惯好像java一样,试图用下面的代码解决问题 new Thread ...

最新文章

  1. 制造业如何将工人师傅的隐性技能转化为显性知识?
  2. _Blank主页——个人浏览器主页定制
  3. 如何使用新的Apache Http Client发出HEAD请求
  4. 会议升降计算机主机,升降式无纸化多媒体会议系统
  5. glide加载图片闪烁_html5 canvas绘制图片
  6. 关于游戏网络设计的问题
  7. Resource punkt not found
  8. 如何隐藏所有的导航栏
  9. UVA12290 Counting Game【数学模拟】
  10. 网路游侠:某硬件WEB应用防火墙配置图示
  11. 没注意开源软件的文档和对应版本号,悲剧了
  12. 使用u盘安装linux操作系统原理
  13. python xps_XPS 15 9560 安装 Ubuntu 18.04
  14. ansys模型导入matlab,CAD三维模型导入ANSYS的万能方法
  15. 手机qq邮箱html,手机QQ邮箱在哪里找
  16. vue table表格中只有表头加竖线分割
  17. 七招搞定微信朋友圈营销
  18. 链表排序时间复杂度为(O(n log n) )
  19. Android 进度条
  20. 使用Arduino的LC测量仪:测量电感和频率

热门文章

  1. mac安装卸载nvm
  2. 4054替代型号SM5201 500mA 线性锂离子电池充电器
  3. 京东集团副总裁周伯文:5G将成为AI发展的新动能
  4. win10安装AutodeskRevit2020、2022遇到序列号页面白屏的问题
  5. 6套毕业设计PPT模板拯救你的毕业答辩
  6. vivo怎么调时间_卡西欧手表怎么调时间 怎么评估卡西欧手表的价格档次
  7. Spring各种PostProcessor : BeanDefinitionRegistryPostProcessor
  8. 手动安装wincap方法
  9. 【图像分割】2021-Swin-Unet CVPR
  10. 【Netty专题】Netty重发机制