`
George_ghc
  • 浏览: 93529 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

android的Handler

阅读更多
【转:】http://www.cnblogs.com/keyindex/articles/1822463.html
前言
  学习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布局:
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    
public void 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    
public void onClick(View v) { 
       switch (v.getId()) { 
       case R.id.btnStartTime:
            startTimer();
            break;
        case R.id.btnStopTime:
            timer.cancel();
            break;
        }
    }
    private synchronized void 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);
    }
    //执行耗时的倒计时任务。
    private void 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
    public void TaskRun() {
        updateTimerValues();
    }     

实现Button按钮的事件处理以此进入倒计时操作。这里使用的Timer 来执行定时操作(其实我们完全可以另起一个线程)。Task类继承了TimerTask类,里面增加了一个任务处理接口来实现回调模式,应此Activity需要实现该回调的接口 ITaskCallBack(这样做是因为我比较不喜欢内部类的编写方法)。
ICallBack接口和Task类
public interface ITaskCallBack {
    void TaskRun();
}
public class Task extends TimerTask {
    private ITaskCallBack iTask;
        public Task(ITaskCallBack iTaskCallBack)    {
        super();
        iTask=iTaskCallBack;
    }
        public void setCallBack(ITaskCallBack iTaskCallBack)    {
        iTask=iTaskCallBack;
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub 
       iTask.TaskRun();
    }} 

这是Java的回调函数的一般写法。
实现CallBack 
    /**     * 实现消息处理     */
    @Override
    public boolean handleMessage(Message msg) {
            switch(msg.what)
        {
        case 0:
            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;
        }
        return false;
    } 

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

  可以看到在onCreate 方法中线程的ID是1(UI线程) 这与 HandlerMessage 进行消息处理时是所作的线程ID是一样的,而消息发送的线程ID则为8非UI线程。
使用Threadle进行实现
Activity类
/*
 * 文件名:	ThreadHandlerrActivity.java
 * 创建日期:	2014-1-6
 */
package com.example.jiji;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler.Callback;
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;

public class ThreadHandlerrActivity extends Activity implements Callback,
		OnClickListener {
	private TextView txt;
	private Button btnStart, btnStop;
	private Handler myHandler;
	private TimerThread timerThread;
	private int Total = 30;

	/** Called when the activity is first created. */
	@Override
	public void 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
	public boolean handleMessage(Message msg) {
		switch (msg.what) {
		case 0:
			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;
		}
		return false;
	}

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



自定义的线程类
/*
 * 文件名: TimerThread.java 创建日期: 2014-1-6
 */
package com.example.jiji;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

/**
 * * 自定义的线程类,通过传入的Handler,和Total 定期执行耗时操作
 * */
public class TimerThread extends Thread {
	public int Total = 60;
	public Handler handler;

	/**
	 * * 初始化构造函数
	 * 
	 * @param mhandler
	 *            handler 用于发送消息
	 ** @param total
	 *            总周期
	 */
	public TimerThread(Handler mhandler, int total) {
		super();
		handler = mhandler;
		Total = total;
	}

	public void stopThread() {
		Total = -1;
	}

	@Override
	public void run() {
		while (true) {
			Total--;
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			if (Total < 0)
				break;
			Message msg = new Message();
			Bundle date = new Bundle();
			// 存放数据
			date.putInt("time", Total);
			msg.setData(date);
			msg.what = 0;
			Log.d("ThreadId",
					"Thread:" + String.valueOf(Thread.currentThread().getId()));
			handler.sendMessage(msg);
		}
		super.run();
	}
}

这里继承了Thread类,也可以直接实现 Runnable接口。
关于POST
  Post的各种方法是把一个Runnable发送给消息队列,它将在到达时进行处理。
POST
/*
 * 文件名:	PostHandler.java
 * 创建日期:	2014-1-6
 */
package com.example.jiji;

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;

public class PostHandler extends Activity implements OnClickListener, Runnable {
	private TextView txt;
	private Button btnStart, btnStop;
	private Handler myHandler;
	private Timer timer;
	private int total = 60;

	@Override
	protected void 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
			public void handleMessage(Message msg) {
				switch (msg.what) {
				case 0:
					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
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.btnStartTime:
			// myHandler.post(this);
			myHandler.postDelayed(this, 1000);
			break;
		case R.id.btnStopTime:
			break;
		}
	}

	@Override
	public void run() {
		while (true) {
			total--;
			if (total < 0)
				break;
			try {
				Thread.sleep(1000);
			} 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 = 0;
			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过去,运行结果是一样的。
代码
/*
 * 文件名:	PostHandler.java
 * 创建日期:	2014-1-6
 */
package com.example.jiji;

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;

public class PostHandler extends Activity implements OnClickListener, Runnable {
	private TextView txt;
	private Button btnStart, btnStop;
	private Handler myHandler;
	private Timer timer;
	private int total = 60;
	private TimerThread timerThread;

	@Override
	protected void 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
			public void handleMessage(Message msg) {
				switch (msg.what) {
				case 0:
					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
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.btnStartTime:
			// myHandler.post(this);
			// myHandler.postDelayed(this, 1000);
			timerThread = new TimerThread(myHandler, 60);
			myHandler.post(timerThread);
			break;
		case R.id.btnStopTime:
			break;
		}
	}

	@Override
	public void run() {
		while (true) {
			total--;
			if (total < 0)
				break;
			try {
				Thread.sleep(1000);
			} 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 = 0;
			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学习笔记之消息机制,异步和多线程
  android handler概念解释
  SDK
分享到:
评论

相关推荐

    模拟Android Handler机制Demo

    【Android Handler机制】是Android应用程序中用于线程间通信的核心组件,它与Looper和Message紧密配合,实现消息的发送、处理以及线程间的同步。在Android应用开发中,尤其是涉及到UI更新时,Handler机制显得尤为...

    Android Handler传值的demo

    在Android开发中,`Handler`、`Message`和`Looper`是实现线程间通信的重要机制,特别是当需要在主线程(UI线程)和工作线程之间传递数据时。本示例“Android Handler传值的demo”将帮助我们深入理解这一机制。 `...

    androidHandler测试的demo

    在“androidHandler测试的demo”中,我们可以预期包含以下内容: 1. 创建自定义`Handler`子类:这个子类可能重写了`handleMessage(Message msg)`方法,根据`msg.what`的值执行不同的操作,比如更新UI元素或执行特定...

    Android Handler消息处理顺序分析

    在Android开发中,Handler、Looper和Message是实现线程间通信的重要组件,它们共同构建了Android的消息处理机制。本文将详细分析Android Handler消息处理的顺序,以及如何利用这些组件进行异步操作。 首先,理解...

    老罗android Handler综合练习 图文混排 服务器端源代码

    【标题】"老罗android Handler综合练习 图文混排 服务器端源代码"涉及的是Android应用开发中的关键知识点,主要集中在Handler机制、图文混排以及服务器端的数据交互。Handler是Android系统中用于线程间通信的重要...

    Android Handler模拟进度条更新

    由于Android的单线程模型,直接在后台线程更新UI是不允许的,这时就需要用到Handler、Looper和Message机制来实现跨线程通信,特别是用于模拟进度条更新,让用户体验更加友好。本篇文章将深入探讨如何使用Android ...

    android handler例子

    在Android开发中,`Handler`是一个至关重要的组件,它用于处理与线程通信相关的任务,尤其是在主线程(UI线程)和工作线程之间。`Handler`、`Looper`和`Message`三者共同构成了Android的消息传递机制。下面将详细...

    Android Handler解析

    # Android Handler解析 在Android应用开发中,保持应用程序的响应性是至关重要的。为了实现这一目标,我们需要确保UI线程不会被阻塞。通常来说,将耗时的任务(如网络请求、复杂计算等)放到后台线程执行可以提高UI...

    android handler的一些测试

    在Android开发中,`Handler`、`Looper`和`Message`是实现线程间通信的重要组件,特别是用于主线程(UI线程)与其他工作线程之间的交互。标题“android handler的一些测试”暗示我们将探讨`Handler`如何在多线程环境...

    Android Handler类详解

    Android Handler类详解 Android Handler类详解 Android Handler类详解 Android Handler类详解

    Android Handler运行原理

    ### Android Handler运行原理详解 #### 一、引言 在Android开发中,线程间通信是非常重要的技术之一,其中Handler机制被广泛应用于实现主线程与子线程之间的数据交互。Handler机制不仅简单易用,而且功能强大,是...

    Android Handler机制的工作原理详析

    Android Handler机制的工作原理详析 Android Handler机制是Android系统中的一种消息机制,负责处理应用程序中的消息处理和线程之间的通信。Handler机制的工作原理可以分为以下几个部分:Looper、MessageQueue、...

    Android handler message奇怪用法详解

    Handler是Android中的一个类,它用于在不同的线程之间发送和处理消息。通常,我们使用Handler配合Looper和Message来实现在主线程(UI线程)中执行后台任务的结果。Looper是消息队列的循环器,它不断检查消息队列并...

    Android Handler 原理分析及实例代码

    在Android开发中,`Handler` 是一个至关重要的组件,它涉及到多线程、UI更新以及消息传递机制。本文将深入探讨 `Handler` 的工作原理,分析其如何在不同线程间进行通信,并通过实例代码来展示其具体用法。 ### ...

    android handler 机制 源码

    在Android系统中,Handler、Looper和Message构成了一个用于线程间通信的重要机制。这个机制使得UI线程可以处理来自其他线程的消息,从而避免了直接在非UI线程操作UI组件,防止应用出现ANR(Application Not ...

    Android Handler 图片浏览器

    在Android开发中,Handler是一种非常重要的组件,它与线程通信密切相关,特别是在更新UI和处理异步任务时。本文将深入探讨如何利用Handler构建一个图片浏览器,并结合计时器(Timer)来实现特定功能。 首先,理解...

    Android Handler机制解析

    Android Handler机制解析 Android Handler机制是Android系统中的一种机制,用于处理线程之间的通信和消息传递。在Android系统中,Handler机制是基于Java的线程机制来实现的。下面将对Android Handler机制进行详细的...

    Android Handler定时更新UI

    在Android应用开发中,Handler是实现线程间通信的关键组件,尤其在涉及到UI更新时,它的作用尤为重要。本文将深入探讨“Android Handler定时更新UI”的相关知识点,以及如何使用CounterDemo来实现这一功能。 首先,...

    android-Handler的使用

    【Android Handler 使用详解】 Handler 是 Android 平台中用于处理线程间通信的关键组件,尤其在涉及 UI(用户界面)更新时,它扮演着至关重要的角色。在 Android 应用程序启动时,系统会默认创建一个主线程,也...

    Android Handler 线程 示例代码

    在Android开发中,`Handler`、`Thread`、`Toast`、`消息队列`以及`线程`是实现UI交互和异步处理的关键概念。本文将深入探讨这些概念,并结合给定的"Android Handler 线程 示例代码"进行详细讲解。 首先,我们来看`...

Global site tag (gtag.js) - Google Analytics