`
xmong
  • 浏览: 263435 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Android和Handler那些事

阅读更多
Android和Handler那些事


目录
1 HANDLER的简单使用 1
2 HANDLER的消息传递 4
3 HANDLER的线程异步 8

1 Handler的简单使用
Handler主要用于异步消息的处理:当调用Handler发送消息方法发出一个消息之后,消息进入一个消息队列,发送消息的方法即刻返回,而Handler的消息处理方法则被调用,逐个的从消息队列中将消息取出,然后对消息进行处理,就是将消息发送和消息处理实现异步化。这种机制通常用来处理相对耗时比较长的操作。
下面通过一个简单的android应用程序来了解Handler的使用
创建一个android应用程序,activity1的实现如下:
package com.example;

import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;


public class Activity1 extends Activity {

	//开始按钮
	private Button start;
	//结束按钮
	private Button end;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity1);
		//根据id获取按钮控件
		start = (Button)findViewById(R.id.start);
		end = (Button)findViewById(R.id.end);
		//给按钮设置事件监听器
		start.setOnClickListener(startClick);
		end.setOnClickListener(endClick);
		
	}
	
	//点击开始按钮的事件监听器
	OnClickListener startClick = new OnClickListener() {
		
		@Override
		public void onClick(View v) {
			System.out.println("start button click!");
			/**
			 * 调用handler的post()方法将线程处理对象放到线程队列中去.
			 * 线程队列中的线程处理对象会被取出执行
			 */
			myHandler.post(myThreadHandler);
		}
	};
	
	//结束按钮的事件监听器
	OnClickListener endClick = new OnClickListener() {
		
		@Override
		public void onClick(View v) {
			System.out.println("end button click!");
			/**
			 * removeCallbacks()方法与post()方法想反,
			 * 调用该方法可以将线程队列中的线程处理对象移出队列
			 */
			myHandler.removeCallbacks(myThreadHandler);
		}
	};
	
	//handler对象
	Handler myHandler = new Handler(){};
	
	//线程处理对象
	Runnable myThreadHandler = new Runnable() {
		
		@Override
		public void run() {
			System.out.println("my thread handler");
			/**
			 * 调用postDelayed()方法可以定时向线程队列中添加线程处理对象。
			 * 第一个参数是Runnable类型:将要执行的线程处理对象
			 * 第二个参数是long类型:延迟的时间,以毫秒为单位 
			 * 即每隔3秒后向线程队列中添加一个线程处理对象
			 */
			myHandler.postDelayed(myThreadHandler, 3000);
		}
	};
	
	//按键事件
	public boolean onKeyUp(int keyCode, KeyEvent event) {
		//当按键为回退键是接受这个activity
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			Activity1.this.finish();
		}
		return true;
	};
	
	

}


运行界面如下:



当点击start按钮时,程序每输出:
start button click!
my thread handler
每隔三秒输出一句:
my thread handler
当点击end按钮后,程序输出:
end button click!

2 Handler的消息传递
上面的例子只是简单handler使用实例,并没有用到handler消息对象来实现消息的异步处理,下面我们来看看怎样利用handler来实现消息异步处理。
基于上面的例子我们可以稍作修改实现一个进度条更新功能。
实现如下:
新创建一个activity实现如下:
package com.example;

import com.example.test_exp_14.R;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;

public class Activity2 extends Activity {

	//开始按钮
	private Button btn;
	//进度条
	private ProgressBar bar;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity2);
		//根据id获取控件对象
		bar = (ProgressBar)findViewById(R.id.bar);
		btn = (Button)findViewById(R.id.btn);
		//给开始按钮设置事件监听器
		btn.setOnClickListener(btnClick);
		
	}
	
	//开始按钮事件监听器
	OnClickListener btnClick = new OnClickListener() {
		
		@Override
		public void onClick(View v) {
			System.out.println("main thread id:"+Thread.currentThread().getId());
			//将进度条设置为可见
			bar.setVisibility(View.VISIBLE);
			//调用handler的post方法将更新线程对象添加到线程队列中进行处理
			updateBarHandler.post(updateThreadHandler);
		}
	};
	
	//handler对象
	Handler updateBarHandler = new Handler(){
		
		/**
		 * 当消息队列中传入消息时会触发该方法
		 */
		public void handleMessage(Message msg) {
			//根据msg消息对象来设置进度条当前的进度
			bar.setProgress(msg.arg1);
			/**
			 * 判断进度条当前进度是否达到最大值
			 * 如果没有达到最大值,则将修改进度条线程对象添加到线程队列中
			 * 如果达到最大值,则将修改进度条线程对象从线程队列中移出
			 */
			if(msg.arg1 < bar.getMax()){
				updateBarHandler.post(updateThreadHandler);
			}else{
				System.out.println("thread id:"+Thread.currentThread().getId()+" process bar end");
				updateBarHandler.removeCallbacks(updateThreadHandler);
			}
		};
	};
	
	//修改进度条线程对象
	Runnable updateThreadHandler = new Runnable() {
		
		int i = 0; //进度条初始值
		int step = 10; //进度条步长
		
		@Override
		public void run() {
			//进度条增加步长
			i = i+step; 
			System.out.println("thread id:"+Thread.currentThread().getId()+" process bar "+i);
			//获取handler的消息对象
			Message msg = updateBarHandler.obtainMessage();
			//将当前进度赋值给msg对象中成员变量保存起来
			msg.arg1 = i;
			try {
				//程序休息1秒
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			/**
			 * handler将消息发送到消息队列中,
			 * 当消息发送到消息队列中后,handler会触发handleMessage()方法来处理消息
			 */
			updateBarHandler.sendMessage(msg);
		}
	};
	
	
	//按键事件
	public boolean onKeyUp(int keyCode, KeyEvent event) {
		//当按键为回退键是接受这个activity
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			Activity2.this.finish();
		}
		return true;
	};
	

}

新创建一个activity布局文件,activity2.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".Activity2" >

     <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:text="@string/hello"/>
    
    <ProgressBar 
        android:id="@+id/bar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:visibility="gone"/>
    
    <Button android:id="@+id/btn"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/ok"></Button>

</LinearLayout>

修改AndroidManifest.xml文件
<application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
	<!--只需要修改入口程序为com.example.Activity2-->
        <activity
            android:name="com.example.Activity2"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

运行程序界面如下:



点击ok按钮后,程序进度条每隔一秒就会更新进度,后台输出如下:
mian thread id:1
thread id:1 process bar 10
thread id:1 process bar 20
thread id:1 process bar 30
thread id:1 process bar 40
thread id:1 process bar 50
thread id:1 process bar 60
thread id:1 process bar 70
thread id:1 process bar 80
thread id:1 process bar 90
thread id:1 process bar 100
thread id:1 process bar end

从输出结果我们可以看到,handler的这种消息传递的异步处理都是在id为1的线程中完成整个handler过程,整个过程实际上是单线程处理的,没有真正实现异步化处理,如果要实现handler消息异步化处理可以通过HandlerThread来实现。

3 Handler的线程异步
基于2中的程序稍作修改可以实现Handler的线程异步处理消息功能。
新创建一个activity实现如下:
package com.example;

import com.example.test_exp_14.R;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

@SuppressLint("HandlerLeak")
public class Activity3 extends Activity{
	
	//开始按钮
	private Button btn;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity2);
		//根据id获取控件对象
		btn = (Button)findViewById(R.id.btn);
		//给开始按钮设置事件监听器
		btn.setOnClickListener(btnClick);
		
	}
	
	//开始按钮事件监听器
	OnClickListener btnClick = new OnClickListener() {
		
		@Override
		public void onClick(View v) {
			System.out.println(Thread.currentThread().getName()+":"+Thread.currentThread().getId());
			/**
			 * 创建handlerThread对象,并启动该对象。
			 * 只有启动该对象才能通过handlerThread对象中的looper对象,否则获取不到looper对象
			 */
			HandlerThread handlerThread = new HandlerThread("handerThread");
			handlerThread.start();
			//通过handlerThread的looper对象来创建handler对象
			MyHander myHandler = new MyHander(handlerThread.getLooper());
			//通过handler对象获取msg对象
			Message msg = myHandler.obtainMessage();
			/**
			 * bundle可以保存消息传送信息,类似java中的hashmap,
			 * bundle的key只能为string类型,value只能为基本类型和常见的引用类型
			 */
			Bundle bundle = new Bundle();
			bundle.putString("name", "xmong");
			bundle.putInt("age", 20);
			//设置msg对象的bundle数据,并将消息发送出去
			msg.setData(bundle);
			msg.sendToTarget();
		}
	};
	
	//内部类handler对象
	class MyHander extends Handler{
	
		public MyHander(Looper looper){
			super(looper);
		}
		/**
		 * 当消息队列中有消息时handler会触发该方法来对消息进行处理
		 */
		@Override
		public void handleMessage(Message msg) {
			System.out.println(Thread.currentThread().getName()+":"+Thread.currentThread().getId());
			//通过消息对象获取bundle数据
			Bundle bundle = msg.getData();
			System.out.println("name:"+bundle.getString("name"));
			System.out.println("age:"+bundle.getInt("age"));
		}
		
	}

}

修改AndroidManifest.xml文件的程序入口为Activity3
运行程序后点击OK按钮,后台输出如下:
main:1
handerThread:9
name:xmong
age:20

从输出结果可以看到activity的主线程id号为1,而消息处理线程的id号为9。整个handler过程由两个线程参与,主线程负责发生消息,而handerThread线程负责处理处理消息。




  • 大小: 143.7 KB
  • 大小: 119.8 KB
分享到:
评论

相关推荐

    Android_Handler详解(一)

    在Android开发中,Handler是一个至关重要的组件,它与线程、消息队列和Looper紧密关联,用于实现不同线程间的通信。本篇将深入探讨Handler的基本概念、使用方法以及其在多线程环境中的作用。 1. Handler是什么? ...

    android 中Handler 的几种写法

    在Android开发中,`Handler`是一个至关重要的组件,它用于在主线程中处理来自其他线程的消息,确保UI更新和事件处理的同步性。本文将详细介绍`Handler`的几种常见写法,以及如何使用`Handler.Callback`进行消息处理...

    android-Handler的使用

    为了解决这个问题,Android 引入了 Handler 和 Looper 的概念。Handler 可以在子线程中创建,但它的实例通常与主线程关联,因为它需要在主线程中执行任务,以便安全地更新 UI。子线程通过调用 `sendMessage()` 或 `...

    Android_Handler消息处理机制

    在Android系统中,Handler、Message和Looper构成了一个关键的异步通信机制,即Handler消息处理机制。这个机制允许Android应用程序在不同的线程间传递消息,处理UI更新等操作,是多线程编程中的重要组成部分。下面...

    模拟Android Handler机制Demo

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

    android handler的一些测试

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

    android demo,使用Handler的postDelay,Runnable run实现延时3秒的splash。

    本示例中的“android demo”就是关于如何利用Handler的`postDelayed`方法和`Runnable`接口来实现一个延时3秒的Splash Screen。下面将详细解释这个过程以及涉及的技术点。 1. **Handler**: Handler是Android中处理...

    Android_Handler的线程队列Demo

    在Android应用开发中,Handler、Looper和Message是实现线程间通信的重要机制。这个"Android_Handler的线程队列Demo"旨在演示如何有效地利用Handler来处理线程间的通信,特别是主线程(UI线程)与工作线程之间的交互...

    Android利用handler在线程之间传递代码

    Handler是Android中的一个消息处理类,它与Looper和Message紧密配合,形成了一个消息队列。通常,主线程(UI线程)中有一个默认的Looper在后台不断循环地检查Message队列,一旦发现有新消息,就会调用Handler的`...

    Android的Handler使用方法总结

    Android的Handler使用方法总结,不错的文档,跟大家分享分享

    androidHandler测试的demo

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

    Android中handler的使用

    在Android开发中,Handler是处理多线程通信的关键机制,尤其在UI更新和异步任务中扮演着重要角色。本文将深入探讨Handler的工作原理、如何使用以及它在处理多线程中的应用。 Handler的主要功能是发送和处理消息,它...

    android多线程handler/message机制详解

    在 Android 中,多线程机制是基于 Handler 和 Message 机制的。 Handler 是什么?Handler 是一个处理器,它负责处理和绑定到该 Handler 的线程中的 Message。每一个 Handler 都必须关联一个 Looper,并且两者是一一...

    Android:Handler的post()方法和Thread的start()方法执行Thread的run()方法的区别

    import android.os.Handler; import android.app.Activity; import android.view.Menu; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { ...

    在Android中使用AsyncTask和Handler线程间交互的方式

    在Android中使用AsyncTask和Handler线程间交互的方式,详情参见博客:http://www.cnblogs.com/plokmju/p/android_AsyncTask.html和http://www.cnblogs.com/plokmju/p/android_Handler.html

    【Android开发入门】Android线程之Handler

    本知识点将深入探讨Android中的Handler机制,它是Android异步处理和消息传递的核心工具,帮助开发者解决多线程环境下UI更新的问题。 一、Android线程基础 Android系统主要分为两个线程:主线程(UI线程)和工作线程...

    Android Thread Handler

    在Android应用开发中,线程(Thread)和Handler是实现多任务并行处理以及界面更新的关键组件。Android系统是一个单线程模型,主线程(UI线程)负责处理用户交互和绘制界面,而其他工作通常需要在后台线程中执行,以...

    Android Handler类详解

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

Global site tag (gtag.js) - Google Analytics