android中的Handler
前言
关键词
android.os.Handler
倒计时程序
- Layout
- <?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主要是用于查看线程是否被阻塞(阻塞时无法拖动)。
- onCreate
- @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, , );
- }
- //执行耗时的倒计时任务。
- 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=;
- 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(这样做是因为我比较不喜欢内部类的编写方法)。
- ICallBack接口和Task类
- 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
- /**
- * 实现消息处理
- */
- @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;
- }
可以看到 实现android.os.Handler.Callback 接口,其实就是对handleMessage()方法进行重写(和内部类的一个区别是,内部类的返回值是Void)。
运行结果

- Activity类
- publicclass ThreadHandlerrActivity extends Activity implements Callback,
- OnClickListener {
- private TextView txt;
- private Button btnStart, btnStop;
- private Handler myHandler;
- private TimerThread timerThread;
- privateint Total=;
- /** 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,);
- timerThread.start();
- break;
- case R.id.btnStopTime:
- timerThread.stop();
- //timerThread.destroy();
- break;
- }
- }
- }
- 自定义的线程类
- **
- * 自定义的线程类,通过传入的Handler,和Total 定期执行耗时操作
- * @author linzijun
- *
- */
- publicclass TimerThread extends Thread {
- publicint Total=;
- public Handler handler;
- /**
- * 初始化构造函数
- * @param mhandler handler 用于发送消息
- * @param total 总周期
- */
- public TimerThread(Handler mhandler,int total)
- {
- super();
- handler=mhandler;
- Total=total;
- }
- @Override
- publicvoid run() {
- while(true)
- {
- Total--;
- if(Total<)
- break;
- try {
- Thread.sleep();
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- Message msg=new Message();
- Bundle date =new Bundle();// 存放数据
- date.putInt("time", Total);
- msg.setData(date);
- msg.what=;
- Log.d("ThreadId", "Thread:"
- + String.valueOf(Thread.currentThread().getId()));
- handler.sendMessage(msg);
- }
- super.run();
- }
- }
这里继承了Thread类,也可以直接实现 Runnable接口。
关于POST
- POST
- publicclass PostHandler extends Activity implements OnClickListener, Runnable {
- private TextView txt;
- private Button btnStart, btnStop;
- private Handler myHandler;
- private Timer timer;
- privateint total =;
- @Override
- protectedvoid onCreate(Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- 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()
- {
- @Override
- publicvoid 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;
- }
- }
- };
- btnStart.setOnClickListener(this);
- btnStop.setOnClickListener(this);
- }
- @Override
- publicvoid onClick(View v) {
- switch (v.getId()) {
- case R.id.btnStartTime:
- //myHandler.post(this);
- myHandler.postDelayed(this, );
- break;
- case R.id.btnStopTime:
- break;
- }
- }
- @Override
- publicvoid run() {
- while(true)
- {
- total--;
- if(total<)
- break;
- try {
- Thread.sleep();
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- Message msg=new Message();
- Bundle date =new Bundle();// 存放数据
- date.putInt("time", total);
- msg.setData(date);
- msg.what=;
- Log.d("ThreadId", "POST:"
- + String.valueOf(Thread.currentThread().getId()));
- myHandler.sendMessage(msg);
- Log.d("ThreadId", "Thread:"
- + String.valueOf(Thread.currentThread().getId()));
- }
- }
- }
使用POST的方式 是将Runnable 一起发送给处理的线程(这里为UI),如果Runnable的操作比较耗时的话那线程将进入阻塞状态。可以看到先运行 Runnable的Run方法 然后在进入 HandleMessage() 。我还尝试了另一种写法,将TimerThreadPOST过去,运行结果是一样的。
- 代码
- package zijunlin.me;
- import java.util.Timer;
- import android.app.Activity;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import android.util.Log;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.TextView;
- publicclass PostHandler extends Activity implements OnClickListener, Runnable {
- private TextView txt;
- private Button btnStart, btnStop;
- private Handler myHandler;
- private Timer timer;
- privateint total =;
- private TimerThread timerThread;
- @Override
- protectedvoid onCreate(Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- 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()
- {
- @Override
- publicvoid 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;
- }
- }
- };
- btnStart.setOnClickListener(this);
- btnStop.setOnClickListener(this);
- }
- @Override
- publicvoid onClick(View v) {
- switch (v.getId()) {
- case R.id.btnStartTime:
- //myHandler.post(this);
- //myHandler.postDelayed(this, 1000);
- timerThread=new TimerThread(myHandler,);
- myHandler.post(timerThread);
- break;
- case R.id.btnStopTime:
- break;
- }
- }
- @Override
- publicvoid run() {
- while(true)
- {
- total--;
- if(total<)
- break;
- try {
- Thread.sleep();
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- Message msg=new Message();
- Bundle date =new Bundle();// 存放数据
- date.putInt("time", total);
- msg.setData(date);
- msg.what=;
- Log.d("ThreadId", "POST:"
- + String.valueOf(Thread.currentThread().getId()));
- myHandler.sendMessage(msg);
- Log.d("ThreadId", "Thread:"
- + String.valueOf(Thread.currentThread().getId()));
- }
- }
- }
可以说POST的各种方法主要是用于 “按计划发送消息或执行某个Runnanble(使用POST方法)”。
android中的Handler的更多相关文章
- Android中使用Handler造成内存泄露的分析和解决
什么是内存泄露?Java使用有向图机制,通过GC自动检查内存中的对象(什么时候检查由虚拟机决定),如果GC发现一个或一组对象为不可到达状态,则将该对象从内存中回收.也就是说,一个对象不被任何引用所指向 ...
- Android中使用Handler造成内存泄露
1.什么是内存泄露? Java使用有向图机制,通过GC自动检查内存中的对象(什么时候检查由虚拟机决定),如果GC发现一个或一组对象为不可到达状态,则将该对象从内存中回收.也就是说,一个对象不被任何引用 ...
- Android中的Handler的机制与用法详解
概述: 很多android初学者对android 中的handler不是很明白,其实Google参考了Windows的消息处理机制, 在Android系统中实现了一套类似的消息处理机制.在下面介绍ha ...
- android中的Handler和Runnable
最近在做一个项目,在网络请求时考虑用Handler进行处理,然后就研究了一下Handler和Runnable 首先在看一下java中的Runnable The Runnable interface s ...
- Android中利用Handler实现消息的分发机制(三)
在第二篇文章<Android中利用Handler实现消息的分发机制(一)>中,我们讲到主线程的Looper是Android系统在启动App的时候,已经帮我们创建好了,而假设在子线程中须要去 ...
- 转:Android中的Handler的机制与用法详解
注:Message类的用法: message的几个参数都可以携带数据,其中arg1与arg2可以携带int类型,what是用户自定义的int型,这样接受者可以了解这个消息的信息. 说明:使用Messa ...
- 深入源代码解析Android中的Handler,Message,MessageQueue,Looper
本文主要是对Handler和消息循环的实现原理进行源代码分析.假设不熟悉Handler能够參见博文< Android中Handler的使用>,里面对Android为何以引入Handler机 ...
- Android中关于Handler的若干思考
在之前的博文中,讲过一些和Handler有关的知识,例如: Android 多线程----AsyncTask异步任务详解 Android多线程----异步消息处理机制之Handler详解 今天再把Ha ...
- 深入探索Android中的Handler
一.概述 1. 什么是Handler Handler是Android消息机制的上层接口,它为我们封装了许多底层的细节,让我们能够很方便的使用底层的消息机制.Handler的最常见应用场景之一便是通过H ...
- Android中的Handler机制
直接在UI线程中开启子线程来更新TextView显示的内容,运行程序我们会发现,如下错 误:android.view.ViewRoot$CalledFromWrongThreadException: ...
随机推荐
- 端午小长假--前端基础学起来04CSS选择器
定义: 选择器{ 样式: } 选择器指明{}中的样式的作用对象,即作用于网页中的哪些元素 <head><meta http-equiv="Content-Type" ...
- Oracle GoldenGate Veridata 12.1.3已经发布
通过GoldenGate Veridata 12.1.3,现在只需要一键点击即可修复数据复制后不一致的数据. veridata 架构
- jQuery 自定义扩展,与$冲突处理
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- hadoop版本和位数的查看方法
目前针对apache hadoop更新的版本较多,由此而产生了两个方面的问题: 1.如何查看运行的集群当中的hadoop的版本的问题. 2.如何查看运行集群当中的hadoop的位数 下面详细的介绍一下 ...
- <转>thinkphp的各种内部函数 D()、F()、S()、C()、L()、A()、I()详解
D.F.S.C.L.A.I 他们都在functions.php这个文件家下面我分别说明一下他们的功能 D() 加载Model类M() 加载Model类 A() 加载Action类L() 获取语言定义C ...
- 国内android帮助文档镜像网站---http://wear.techbrood.com/develop/index.html
http://wear.techbrood.com/develop/index.html
- 玩转渗透神器Kali:Kali Linux作为主系统使用的正确姿势TIPS
Kali Linux 前身是著名渗透测试系统BackTrack ,是一个基于 Debian 的 Linux 发行版,包含很多安全和取证方面的相关工具. 本文假设你在新装好的kali linux环境下… ...
- 北大poj-1001
Description Problems involving the computation of exact values of very large magnitude and precision ...
- C++11 不抛异常的new operator
在google cpp style guide里面明确指出:we don't use exceptions C++11的noexcept关键字为这种选择提供了便利. C++11以前,提及malloc和 ...
- UITableView详解(1)
一,UITableView控件使用必备,红色部分是易错点和难点 首先创建一个项目,要使用UITableView就需要实现协议<UITableViewDataSource>,数据源协议主要完 ...