- 浏览: 16402 次
- 性别:
最新评论
Android学习笔记(五) handler
- 博客分类:
- Android学习笔记
一、基本概念
主要用于"异步消息"的处理.例如:
在手机使用时,经常碰到这种情况:比如在我们下载的时候,若是将下载方法单独为一个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.GridView实现宫式布局
2011-11-10 14:19 0应一位朋友的要求,我 ... -
广播机制
2011-09-07 11:00 720一、Android广播机制的介绍 BroadcastRec ... -
Android学习笔记(9)XML文件解析
2011-08-29 16:49 1058XML(可扩展标记语言) 通常有两种方式对XML文件今夕解析 ... -
Android学习笔记(8)ContentProvider
2011-08-29 14:02 724一、ContentProvider概念 基本概念: 1、C ... -
Android学习笔记(七)输出流Log、download、写入SDCard
2011-08-26 11:04 2589一、输出流Log andro ... -
Android学习笔记(六)SQLite
2011-08-25 15:28 1095一、SQLite介绍 关系型数据库:SQLite-基于文本 ... -
Android学习笔记(四)CheckBox、RadioGroup、ProgressBar、ListView、Spinner
2011-08-24 09:45 2421一、多选按钮-CheckBox 用法:首先也是通过控件ID来 ... -
Android学习笔记(三)UI布局
2011-08-24 09:37 1792一、线性布局-LinearLayout(至上而下布局) &l ... -
Android学习笔记(二)Activity生命周期、task、对话框风格的Activity
2011-08-23 17:40 1624Activity的七个生命周期 ... -
Android学习笔记(一)Activity
2011-08-23 17:36 789一、Activity基础知识 1、一个Activity就是一 ...
相关推荐
Handler在android里负责发送和处理消息。它的主要用途有(或者是干什么的): 1)执行计划任务,按计划(定时)发送消息或执行某个Runnanble(使用POST方法); 2)线程间通信,把从其他线程中发送来的消息放入消息...
这是Pro Android学习系列中Android Service部分的例子源代码。相关学习笔记见:http://blog.csdn.net/flowingflying/article/details/6212512
在android中有一个规则:考虑到安全性,子线程不能动态的改变主线程中组件的属性值。 但为了执行一些耗时操作,往往会将它们放在子线程中,执行完毕要更新主线程中的UI,所以就有了handler消息处理机制。 handler就...
3.android学习笔记--activity生命周期&handler使用 4.android学习笔记--HandlerThread和Bundle 5.android学习笔记--SQLite 6.android学习笔记--下载文件 7.android学习笔记--Content Provider 8.android学习笔记--...
包括环境搭建教程、创建模拟器、新建helloworld程序、电话拨号器、软件部署到模拟器、短信发送器、线性布局、相对布局、日志、activity、Android进程线程及优先级、Android UI线程阻塞及优化、广播接受者、Service...
Handler处理机制中,需要Looper来动态的进行循环,以此来不断将MessageQueue的数据取出。 在主线程中,Looper和MessageQueue已经在创建好的,因此我们不用自己创建它们就能用。 而在子线程中,如果我们想用Handler的...
xamarin学习笔记A13(安卓Handler异步消息处理)Android中只能在主线程进行UI操作,不能在子线程操作,要根据子线程执行的结果来更新UI时,需要用到安卓异步消息处理机制。
1、查看网络上的图片 2、主线程阻塞-ANR 3、刷新UI-Handler 4、在本地缓存图片-例如微信的图片 5、获取开源代码 6、显示一个新闻客户端 7、使用GET方式提交表单数据 8、使用POST方式提交表单
个人学习Android的东西,绝对经典,不容错过,或许很多的问题你都会在我这里找到一种似曾相识的感觉,
上一次写完Binder学习笔记之后,再去看一遍Activity的启动流程,因为了解了Binder的基本原理,这次看印象会更深一点,学习效果也比以前好很多。本来打算直接来写Activity的启动流程的,但总觉得Handler也需要写一下...
android性能优化整理 android性能优化整理 本人学习使用的笔记 长期更新 欢迎star QQ879689064 Handler产生的内存泄露
Android Demo, 学习过程中的一些笔记 chapter3 ~ chapter13 为 「Android 群英传」的 Demo ,做了部分修改并在上面增加了一些注释及评论用于备忘 art_Chapter[chapterNumber] 为 「Android 开发艺术探索」的 Demo ,...
这是一个基于Bmob平台实现的记事本源码,代码中比较详细的注释解释了如何借助Bmob平台强大的后台处理功能实现...同时案例里面的侧滑菜单、自定义Adapter, ListView, Handler, 更新ListView等都是可供学习参考的。
学习时候,所做的一些笔记。方便之后复习查阅。 一. Notes for Algortihms 顺时针打印链表矩阵 链表中环的入口节点 树中两个节点的最低公共祖先 判断是否为平衡二叉树-解法二 机器人运动的范围 矩阵中的路径 滑动窗口...