`
suuu
  • 浏览: 16925 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

Android学习笔记(五) handler

 
阅读更多

一、基本概念

主要用于"异步消息"的处理.例如:

 在手机使用时,经常碰到这种情况:比如在我们下载的时候,若是将下载方法单独为一个Activity的时候,那么下载时,其他的Activity是没有响应的,那么这个时候整部手机就处于了当机的状态,而Handler就是用来解决这个问题的.

 意思就是说,将下载放在一个单独的线程,那么当这个线程执行的时候,并不会影响该Activity的线程.

二、使用方法

 通过调用handler的post方法实现线程的操作.

一个最简单的Handler例子:

XML文件:

 

<?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"
    android:weightSum="1">
<Button 
		android:id="@+id/start"
		android:text="@string/opt_start"
		android:layout_height="wrap_content"
		android:layout_weight="0.38" 
		android:layout_width="202dp"/>
<Button 
		android:layout_height="wrap_content" 
		android:id="@+id/end" 
		android:text="@string/opt_end" 
		android:layout_weight="0.38" 
		android:layout_width="202dp">
		</Button>
</LinearLayout>

 

 

Handler文件:

 

package com.hadler;


import android.accounts.Account;
import android.accounts.OnAccountsUpdateListener;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.text.style.UpdateAppearance;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class Handlertest extends Activity {
    /** Called when the activity is first created. */
	private Button start;
	private Button end;
	
	OnClickListener start_listen = null;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        start = (Button)findViewById(R.id.start);
        end = (Button)findViewById(R.id.end);
        
        start_listen = (new OnClickListener(){
        	
        	@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
        		//调用handler的post方法,将要执行的线程对象加到队列当中
				handler.post(updateThread);
			}
        	
        });
			

        start.setOnClickListener(start_listen);
        
        OnClickListener end_listen = (new OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				handler.removeCallbacks(updateThread);
				
			}
		});
        end.setOnClickListener(end_listen);
    }
    
    	
    //创建一个Handler对象
    Handler handler = new Handler();
    
    //线程类,实现Runnable接口,将要执行的操作写在run方法中
    Runnable updateThread = new Runnable(){

		@Override
		public void run() {
			// TODO Auto-generated method stub
			System.out.println("UpdateThread");
			//在run方法内部,执行postDelayed或者post方法
			handler.postDelayed(updateThread, 3000);
			}
    	
    };
    
}

 

这个例子中可看到LogCat中每隔3秒中就打印一句UpdateThread.

即是,不影响当前Acvtivity,调用新的进程完成的代码段. 也就是异步处理.

 

 

三、使用handler更新ProgressBar进度条 

接着看一个例子,更新进度条的

 

 package mars.barhandler;

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

public class TestBarHandler extends Activity {
    /** Called when the activity is first created. */
	//声明控件变量
	ProgressBar bar = null;
	Button startButton = null;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //根据控件的ID得到代表控件的对象,并为按钮设置监听器
        bar = (ProgressBar)findViewById(R.id.bar);
        startButton = (Button)findViewById(R.id.startButton);
        startButton.setOnClickListener(new ButtonListener());
    }
    //当点击startButton按钮时,就会执行ButtonListener的onClick方法
    class ButtonListener implements OnClickListener{

		@Override
		//匿名内部类
		public void onClick(View v) {
			// TODO Auto-generated method stub
			//进度条设置为可见的
			bar.setVisibility(View.VISIBLE);
			//将线程对象updateThread马上加入到消息队列当中,立马执行线程,执行线程就是执行run方法
			updateBarHandler.post(updateThread);
		}
    	
    }
    //使用匿名内部类来复写Handler当中的handleMessage方法
    Handler updateBarHandler = new Handler(){

		@Override
		public void handleMessage(Message msg) {
			//对已经压入消息队列的msg加入到线程队列里面
			bar.setProgress(msg.arg1)//设置进度条的当前值			
Bundle bundle = msg.getData(); updateBarHandler.post(updateThread); System.out.println("test---->" + bundle.getString("test")); } }; //线程类,该类使用匿名内部类的方式进行声明 Runnable updateThread = new Runnable(){ int i = 0 ; @Override public void run() { System.out.println("Begin Thread" + i); i = i + 10 ; //得到一个消息对象,Message类是由Android操作系统提供 Message msg = updateBarHandler.obtainMessage(); //将msg对象的arg1参数的值设置为i,用arg1和arg2这两个成员变量传递消息,优点是系统性能消耗较少 msg.arg1 = i ; Bundle bundle = new Bundle(); bundle.putString("test", "test bundle"); msg.setData(bundle); try { //设置当前线程睡眠1秒 Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } //将msg对象加入到消息队列当中 if( i > 100){ //如果当i的值为100时,就将线程对象从handler当中移除 updateBarHandler.removeCallbacks(updateThread); System.out.println(">>>>>>"); }else{ //将msg压入到消息队列中,压入之后就会去执行上面的handleMessage方法 //每次执行完一次压入,上面代码就讲msg加入线程队列,只要i小于100,就一直循环这个操作 updateBarHandler.sendMessage(msg); System.out.println("<<<<<<"); } } }; class MyThread extends Thread{ public void run(){ } } }

 

 原理如下:

 

 

sendMessage执行完之后就返回,继续执行他的方法,不管handlerMessage执行不执行,这就是异步.

 

 

四、Handler与线程

当使用handler.post()方法时,并不是调用线程对象的start方法,而是在原本线程上直接调用run()方法。 所以说,Runnable这个线程在实际使用时并不把它当作一个新的线程.

 

只有当实例化了一个Runnable对象,并把该对象当作参数生成Thread对象的时候,才会启用新的进程,看下面两个代码:

 

不启动新的线程:

 

public class HandlerTest extends Activity {
	private Handler handler = new Handler();
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		/**这里如果先执行Handler的post方法,然后在对控件进行布局,若10秒钟之后才布局完成
		 * 则说明并没有启动了新的线程,onCreate函数和run函数是运行在同一个线程中的*/
		handler.post(r);
		setContentView(R.layout.main)
/**Thread.currentThread()中currentThread()是Thread的一个静态方法 * 返回的是当前的进程对象,为了帮助理解可以写为Thread t = Thread.currentThread() * 也就是说现在变量t就等于Thread.currentThread()。 * 有了上面的简化,现在可以写为t.getId() * 也就是说只是调用了t的一个方法.*/ System.out.println("activity--->" + Thread.currentThread().getId()); System.out.println("activityname--->" + Thread.currentThread().getName()); } Runnable r = new Runnable(){ @Override public void run() { System.out.println("handler--->" + Thread.currentThread().getId()); System.out.println("handlername--->" + Thread.currentThread().getName()); try { Thread.sleep(10000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; }

 

 

启动新的进程:

 

public class HandlerTest extends Activity {
	private Handler handler = new Handler();
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.main);

		/**标准的java启动线程的方法,在下面实例化一个Runnable的对象r,并将r当作参数生成Thread的对象,
		 * 这时候的线程就不一样了*/
		Thread t = new Thread(r) ;
		t.start();
		/**Thread.currentThread()中currentThread()是Thread的一个静态方法
		 * 返回的是当前的进程对象,为了帮助理解可以写为Thread t = Thread.currentThread()
		 * 也就是说现在变量t就等于Thread.currentThread()。
		 * 有了上面的简化,现在可以写为t.getId()
		 * 也就是说只是调用了t的一个方法.*/
		System.out.println("activity--->" + Thread.currentThread().getId());
		System.out.println("activityname--->" + Thread.currentThread().getName());
	}
	

	Runnable r = new Runnable(){
		@Override
		public void run() {
			
			System.out.println("handler--->" + Thread.currentThread().getId());
			System.out.println("handlername--->" + Thread.currentThread().getName());
			try {
				Thread.sleep(10000);

			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	};

}

五、Bundle的使用方法

Bundle是一个以string为键,可以有其他数据类型作为值的一个mapping.相当于将所有数据类型打成一个包进行传递.

可以将Bundle看成一个特殊的map,它的key和value都是object类型的,也就是说它的值可以以任意的引用数据类型,但是键永远都是String类型的.

 

 

 

六、在新线程当中处理消息的方法 


 在新的线程中,使用Bundle来处理消息的例子:

 

package mars.handler;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;

public class HandlerTest2 extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		//打印了当前线程的ID
		System.out.println("Activity-->" + Thread.currentThread().getId());
		
		/**生成一个HandlerThread对象,实现了使用Looper来处理消息队列的功能
		这个类由Android应用程序框架提供*/
		HandlerThread handlerThread = new HandlerThread("handler_thread");
		/**在使用HandlerThread的getLooper()方法之前,必须先调用该类的start();
		 * 否则调用getLooper取得的Looper对象是为空的(Null)*/
		handlerThread.start();
		//使用getLooper()方法,得到线程里面使用的Looper对象,传给MyHandler,然后调用下面的构造函数
		MyHandler myHandler = new MyHandler(handlerThread.getLooper());
		
		/**获取消息对象*/
		Message msg = myHandler.obtainMessage();
		//将message发送给目标对象,由哪个Handler生成Message,哪个就是目标对象
		msg.sendToTarget();
	
		
		//将msg发送到目标对象,所谓的目标对象,就是生成该msg对象的handler对象
		Bundle b = new Bundle();
		b.putInt("age", 20);
		b.putString("name", "Jhon");
		
		//b是Bundle类型的对象,将b的参数放在msg中
		msg.setData(b);
		//发送messaga到目标MyHandler
		msg.sendToTarget();
	}
	
	//构造函数
	class MyHandler extends Handler{
		public MyHandler(){
			
		}
		//将线程绑定在looper对象上
		public MyHandler(Looper looper){
			super(looper);
		}
		@Override
		/**Message的handlerMessage方法*/
		public void handleMessage(Message msg) {
			//取出对象
			Bundle b = msg.getData();
			//定义两个变量age和name来接收数据
			int age = b.getInt("age");
			String name = b.getString("name");
			
			System.out.println("age is " + age + ", name is" + name);
			System.out.println("Handler--->" + Thread.currentThread().getId());
			System.out.println("handlerMessage");
		}
	}
}
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

分享到:
评论

相关推荐

    android_handler学习笔记

    Handler在android里负责发送和处理消息。它的主要用途有(或者是干什么的):  1)执行计划任务,按计划(定时)发送消息或执行某个Runnanble(使用POST方法);  2)线程间通信,把从其他线程中发送来的消息放入消息...

    Pro Android学习:了解Handler小例子

    这是Pro Android学习系列中Android Service部分的例子源代码。相关学习笔记见:http://blog.csdn.net/flowingflying/article/details/6212512

    android学习笔记之handler消息处理机制1

    在android中有一个规则:考虑到安全性,子线程不能动态的改变主线程中组件的属性值。 但为了执行一些耗时操作,往往会将它们放在子线程中,执行完毕要更新主线程中的UI,所以就有了handler消息处理机制。 handler就...

    android 学习笔记(全全整理)

    Android学习笔记全全整理,是针对想要深入理解并掌握Android开发技术的学习者们的一份宝贵资源。这份笔记涵盖了从基础到高级的多个方面,旨在帮助读者建立起完整的Android知识体系。以下将详细介绍其中可能包含的...

    Android学习笔记.rar

    这份“Android学习笔记”涵盖了从基础到进阶的Android开发知识,旨在帮助开发者深入理解Android系统,并具备开发高质量Android应用的能力。 一、Android系统架构 Android系统分为四个主要层次:Linux内核、系统库和...

    Android基础学习笔记

    Android基础学习笔记主要涵盖了一系列关于Android开发的基本概念和关键组件,以下是这些知识点的详细解析: 1. **Activity**: 是Android应用程序的基本单元,它代表用户在屏幕上看到的一个界面。每个Activity都必须...

    java、linux、Android 学习笔记

    【Android学习笔记】 Android是一个开源的移动操作系统,主要应用于智能手机和平板电脑。它由Google主导并开源,基于Linux内核。学习Android开发,你需要熟悉Java或Kotlin语言,理解Android SDK、Android Studio...

    android学习笔记.zip

    Android学习笔记是一个专门为初学者和自学者准备的资源包,旨在帮助他们系统地掌握Android开发的基础知识。这个压缩包可能包含一系列的文档、教程、代码示例和其他学习材料,以全面介绍Android应用开发的各个方面。 ...

    Android学习笔记.pdf

    包括环境搭建教程、创建模拟器、新建helloworld程序、电话拨号器、软件部署到模拟器、短信发送器、线性布局、相对布局、日志、activity、Android进程线程及优先级、Android UI线程阻塞及优化、广播接受者、Service...

    xamarin学习笔记A13(安卓Handler异步消息处理)

    本篇笔记主要聚焦于Xamarin中的Android Handler异步消息处理机制,这是Android UI线程与后台工作线程之间通信的关键技术。 一、Android线程模型 Android系统规定,所有的UI操作必须在主线程(也称为UI线程)中进行...

    Android学习笔记之Handler处理机制的Looper

    Handler处理机制中,需要Looper来动态的进行循环,以此来不断将MessageQueue的数据取出。 在主线程中,Looper和MessageQueue已经在创建好的,因此我们不用自己创建它们就能用。 而在子线程中,如果我们想用Handler的...

    android 很好的学习笔记

    【Android学习笔记详解】 在移动应用开发领域,Android操作系统占据着重要的地位,为开发者提供了丰富的平台和无限的可能性。"Android很好的学习笔记"是一份专为初学者设计的资源,旨在帮助那些想要踏入Android开发...

    Android学习笔记.zip

    Android学习笔记是一个全面涵盖Android应用开发的资源集合,旨在帮助初学者和有经验的开发者深入理解和掌握Android平台的各个方面。这个压缩包可能包含了详细的教程、示例代码、项目实践以及相关的学习指南,以促进...

    android 学习笔记整理

    在Android学习过程中,掌握基础知识是至关重要的。这份"android 学习笔记整理"包含了作者在学习Android时积累的详尽资料,旨在为初学者提供一个系统化的学习路径和参考资料。 首先,Android是一种开源的操作系统,...

    Android学习笔记总结初学者必看.rar_Android java_android

    在Android学习之旅中,初学者会遇到各种概念和实践技巧,这份"Android学习笔记总结初学者必看"的文档正是为了帮助他们系统性地掌握这一领域。以下是对这份压缩包内容的详细解读。 首先,Android是由Google开发的一...

    ANDROID STUDIO 个人学习笔记

    1. Android Studio学习笔记的概览 - 笔记是作者在Android Studio 3.2版本上进行安卓开发学习时遇到的问题记录,涵盖三个多月的学习心得。 2. Android颜色设置 - 学习如何在Android应用中设置和使用颜色,颜色的...

    Android基础笔记

    Android 基础笔记 Android 基础笔记是 Android 开发的入门知识点总结,涵盖了 Android 开发的基础知识点,从 Android 发展史到自定义 ContentProvider 的实现。 一、Android 发展史 Android 的发展史可以追溯到 ...

    最新最全的Android开发笔记

    除此之外,笔记还涉及了Android的多线程处理,包括Handler、Looper、Message的使用,以及AsyncTask的介绍。这些内容对于优化应用性能和实现后台操作至关重要。 网络编程是现代应用不可或缺的一部分,笔记中详细讲述...

    Android开发笔记全集

    《Android开发笔记全集》是一份综合性的学习资源,涵盖了Android应用开发的多个核心领域,旨在帮助开发者系统地掌握Android平台的开发技能。这个压缩包包含的文件名为“Android开发笔记”,暗示着它可能是一个系列的...

    android学习笔记

    Android学习笔记是一个全面且实用的学习资源,旨在帮助开发者或初学者深入理解Android操作系统以及如何在该平台上构建应用程序。这份笔记涵盖了Android开发的各个方面,包括基础知识、界面设计、数据存储、网络通信...

Global site tag (gtag.js) - Google Analytics