免费论文网 首页

handler机制详解

时间:2018-11-09 11:33 来源:免费论文网

篇一:Android Handler机制详解:在线程中新建Handler

Android Handler机制详解:在线程中新建Handler

在android中提供了一种异步回调机制Handler,使用它,我们可以在完成一个很长时间的任务后做出相应的通知

handler基本使用:

在主线程中,使用handler很简单,new一个Handler对象实现其handleMessage方法,在handleMessage中

提供收到消息后相应的处理方法即可,这里不对handler使用进行详细说明,在看本博文前,读者应该先掌握handler的基本使用,我这里主要深入描述handler的内部机制

.现在我们首先就有一个问题,我们使用myThreadHandler.sendEmptyMessage(0);发送一个message对象,那么Handler是如何接收该message对象并处理的呢?我先画一个数据结构图:

从这个图中我们很清楚可以看到调用sendEmptyMessage后,会把 Message对象放入一个MessageQueue队列,该队列属于某个Looper对象,每个Looper对象通过 ThreadLocal.set(new Looper())跟一个Thread绑定了,Looper对象所属的线程在Looper.Loop方法中循环执行从MessageQueue队列读取 Message对象,并把Message对象交由Handler处理,调用Handler的dispatchMessage方法。

现在我们再来看一下使用Handler的基本实现代码:

1

2

3

4

5

6

7

8

9

10

// 主线程中新建一个handler normalHandler = new Handler() { public void handleMessage(android.os.Message msg) {btnSendMsg2NormalHandler.setText("normalHandler");Log.d(Constant.TAG, MessageFormat.format("Thread[{0}]--normalHandler Thread.currentThread() .getName())); } };

... handleMessage run...",

//发送消息到hanlder

1

myThreadHandler.sendEmptyMessage(0);

你现在已经很清楚了sendEmptyMessage到 handleMessage的过程,途中经过Looper.MessageQueue队列,转由Looper所在的线程去处理了,这是一个异步的过程,当然Looper所在的线程也可以是sendEmptyMessage所在的线程。

看了上面你也许还是迷惑不解,那么什么要Looper了,跟我们要用的Handler又有啥鸟关系呢?

我在前面一直强调在主线程中使用handler,为什么要这么说呢,因为你在自己new一个新线程中去像我前面那样简单建立一个Handler,程序执行是会报错的:

java.lang.RuntimeException: Can't create handler inside thread that has not called 1

2

3

4

Looper.prepare()at android.os.Handler.(Handler.java:121)at com.cao.android.demos.handles.HandleTestActivity$MyThread$1.(HandleTestActivity.java:86)at

com.cao.android.demos.handles.HandleTestActivity$MyThread.run(HandleTestActivity.java:86)

为什么在主线程中不会报错,而在自己新见的线程中就会报这个错误呢?很简单,因为主线程它已经建立了Looper,你可以打开ActivityThread的源码看一下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

public static final void main(String[] args) {SamplingProfilerIntegration.start(); Process.setArgV0(" "); Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread();thread.attach(false); Looper.loop(); if (Process.supportsProcesses()) { throw new RuntimeException("Main thread loop unexpectedly exited");} thread.detach();String name = (thread.mInitialApplication != null) ? thread.mInitialApplication.getPackageName() : "";Slog.i(TAG, "Main thread of " + name + " is now exiting"); }

在 main函数中它已经做了这个事情了,为什么要调用 Looper.prepareMainLooper(); Looper.loop();我们可以进去看一下,在prepareMainLooper方法中新建了一个looper对象,并与当前进程进行了绑定,而在Looper.loop方法中,线程建立消息循环机制,循环从MessageQueue获取Message对象,调用 msg.target.dispatchMessage(msg);进行处理msg.target在

myThreadHandler.sendEmptyMessage(0)设置进去的,因为一个Thead中可以建立多个Hander,通过 msg.target保证MessageQueue中的每个msg交由发送message的handler进行处理,那么Handler又是怎样与 Looper建立联系的呢,在Handler构造函数中有这样一段代码:

1

2

3

4

5

6

mLooper = Looper.myLooper();if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()");}mQueue = mLooper.mQueue;

在新建Handler时需要设置mLooper成员,Looper.myLooper是从当前线程中获取绑定的Looper对象: 1

2

3

public static final Looper myLooper() {return (Looper)sThreadLocal.get(); }

若Looper对象没有创建,就会抛异常”Can’t create handler inside thread that has not called Looper.prepare()”

这跟我前面讲的是一致的。所以我们在一个新线程中要创建一个Handler就需要这样写:

class MyThread extends Thread {

1

2 public void run() {

3 Log.d(Constant.TAG, MessageFormat.format("Thread[{0}]-- run...", 4 Thread

5 .currentThread().getName()));

6 // 其它线程中新建一个handler

7 Looper.prepare();// 创建该线程的Looper对象,用于接收消息,在非主线8 程中是没有looper的所以在创建handler前一定要使用prepare()创建一个Looper

9 myThreadHandler = new Handler() {

10public void handleMessage(android.os.Message msg) { 11 Log.d(Constant.TAG,

12 MessageFormat.format("Thread[{0}]--myThreadHandler handleMessage run...", Thread 13.currentThread().getName())); 14}

15 };

16 Looper.myLooper().loop();//建立一个消息循环,该线程不会退出}

}

现在,你应该对Handler的机制有所了解了吧,若有什么疑问,欢迎在评论中提出

在其它线程中Handler使用主线程的Looper

前面我说了在新线程中要新建一个Handler需要调用Looper.prepare();也有另一种方法就是使用主线程中的Looper,那就不必新建Looper对象了:

1 threadMainLoopHandler =new Handler(Looper.getMainLooper()){

2public void handleMessage(android.os.Message msg) {

3 Log.d(Constant.TAG,

4 MessageFormat.format("Thread[{0}]--threadMainLoopHandler handleMessage run...", Thread 5.currentThread().getName())); 6}

7//该handleMessage方法将在mainthread中执行

};

这时候注意不要在handleMessage做太多的操作,因为它在主线程中执行,会影响主线程执行ui更新操作。

使用Message.callback回调

1

2

3

4

5

6

7

8

9

10

11

12

public void dispatchMessage(Message msg) {if (msg.callback != null) { handleCallback(msg);} else { if (mCallback != null) { if (mCallback.handleMessage(msg)) {return; } } handleMessage(msg);} }

从 dispatchMessage定义可以看出,如果Message对象自带callback对象,handler不会执行handleMessage方法而是执行message.callback中定义的run方法,当然callback还是在handler关联的looper所绑定的线程中执行的。实际上Handler.post(Runnable r)方法就是把r添加到一个msg.callback的,也就是说,下面两种写法,没有什么区别:

1.使用Message.callback

1Message msg = Message.obtain(myThreadHandler,new Runnable() { 2

3@Override

4public void run() {

5 Log.d(Constant.TAG,

6 MessageFormat.format("Thread[{0}]--myThreadHandler.Message.callback.run",

7Thread.currentThread().getName()));

8}

9 });

myThreadHandler.sendMessage(msg);

2.使用Handler.post

1 myThreadHandler.post(new Runnable() {

2

3@Override

4public void run() {

5 Log.d(Constant.TAG,

6 MessageFormat.format("Thread[{0}]--myThreadHandler.Message.callback.run", 7Thread.currentThread().getName())); 8}

});

原文链接:http://blog.csdn.net/stonecao/article/details/6417364

Tags:

AndroidAndroid 线程Android-HandlerAndroid-Looper主线程 Looper

篇二:Android Handler机制

Android Handler机制

分类: android应用开发2011-05-13 14:48 104529人阅读 评论(53) 收藏 举报

androidthreadcallbacknull数据结构string

在android中提供了一种异步回调机制Handler,使用它,我们可以在完成一个很长时间的任务后做出相应的通知

handler基本使用:

在主线程中,使用handler很简单,new一个Handler对象实现其handleMessage方法,在handleMessage中

提供收到消息后相应的处理方法即可,这里不对handler使用进行详细说明,在看本博文前,读者应该先掌握handler的基本使用,我这里主要深入描述handler的内部机制

.现在我们首先就有一个问题,我们使用

myThreadHandler.sendEmptyMessage(0);发送一个message对象,那么Handler是如何接收该message对象并处理的呢?我先画一个数据结构图:从这个图中我们很清楚可以看到调用sendEmptyMessage后,会把Message对象放入一个MessageQueue队列,该队列属于某个Looper对象,每个Looper对象通过ThreadLocal.set(new Looper())跟一个Thread绑定了,Looper对象所属的线程在Looper.Loop方法中循环执行从MessageQueue队列读取Message对象,并把Message对象交由Handler处理,调用Handler的dispatchMessage方法。

现在我们再来看一下使用Handler的基本实现代码:

// 主线程中新建一个handler

normalHandler = new Handler() {

public void handleMessage(android.os.Message msg) {

btnSendMsg2NormalHandler.setText("normalHandler");Log.d(Constant.TAG,

MessageFormat.format("Thread[{0}]--normalHandler handleMessage run...", Thread.currentThread()

.getName()));

}

};

...

//发送消息到hanlder

myThreadHandler.sendEmptyMessage(0);

你现在已经很清楚了sendEmptyMessage到handleMessage的过程,途中经过Looper.MessageQueue队列,转由Looper所在的线程去处理了,这是一个异步的过程,当然Looper所在的线程也可以是sendEmptyMessage所在的线程。

看了上面你也许还是迷惑不解,那么什么要Looper了,跟我们要用的Handler又有啥鸟关系呢?

我在前面一直强调在主线程中使用handler,为什么要这么说呢,因为你在自己new一个新线程中去像我前面那样简单建立一个Handler,程序执行是会报错的:

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

at android.os.Handler.<init>(Handler.java:121)

at

com.cao.android.demos.handles.HandleTestActivity$MyThread$1.<init>(HandleTestActivity.java:86)

at

com.cao.android.demos.handles.HandleTestActivity$MyThread.run(HandleTestActivity.java:86)

为什么在主线程中不会报错,而在自己新见的线程中就会报这个错误呢?很简单,因为主线程它已经建立了Looper,你可以打开ActivityThread的源码看一下:

public static final void main(String[] args) {

SamplingProfilerIntegration.start();

Process.setArgV0("<pre-initialized>");

Looper.prepareMainLooper();

ActivityThread thread = new ActivityThread();

thread.attach(false);

Looper.loop();

if (Process.supportsProcesses()) {

throw new RuntimeException("Main thread loop unexpectedly exited");}

thread.detach();

String name = (thread.mInitialApplication != null)

? thread.mInitialApplication.getPackageName()

: "<unknown>";

Slog.i(TAG, "Main thread of " + name + " is now exiting");

}

在main函数中它已经做了这个事情了,为什么要调用

Looper.prepareMainLooper(); Looper.loop();我们可以进去看一下,在

prepareMainLooper方法中新建了一个looper对象,并与当前进程进行了绑定,而在Looper.loop方法中,线程建立消息循环机制,循环从MessageQueue获取Message对象,调用 msg.target.dispatchMessage(msg);进行处理

msg.target在myThreadHandler.sendEmptyMessage(0)设置进去的,因为一个Thead中可以建立多个Hander,通过msg.target保证MessageQueue中的每

个msg交由发送message的handler进行处理,那么Handler又是怎样与Looper建立联系的呢,在Handler构造函数中有这样一段代码:

mLooper = Looper.myLooper();

if (mLooper == null) {

throw new RuntimeException(

"Can't create handler inside thread that has not called

Looper.prepare()");

}

mQueue = mLooper.mQueue;

在新建Handler时需要设置mLooper成员,Looper.myLooper是从当前线程中获取绑定的Looper对象:

public static final Looper myLooper() {

return (Looper)sThreadLocal.get();

}

若Looper对象没有创建,就会抛异常"Can't create handler inside thread that has not called Looper.prepare()"

这跟我前面讲的是一致的。所以我们在一个新线程中要创建一个Handler就需要这样写:

class MyThread extends Thread {

public void run() {

Log.d(Constant.TAG, MessageFormat.format("Thread[{0}]-- run...", Thread

.currentThread().getName()));

// 其它线程中新建一个handler

Looper.prepare();// 创建该线程的Looper对象,用于接收消息,在非主线程中是没有looper的所以在创建handler前一定要使用prepare()创建一个Looper

myThreadHandler = new Handler() {

public void handleMessage(android.os.Message msg) { Log.d(Constant.TAG,

MessageFormat.format("Thread[{0}]--myThreadHandler handleMessage

run...", Thread

.currentThread().getName()));

}

};

Looper.myLooper().loop();//建立一个消息循环,该线程不会退出 }

}

现在,你应该对Handler的机制有所了解了吧,若有什么疑问,欢迎在评论中提出

在其它线程中Handler使用主线程的Looper

前面我说了在新线程中要新建一个Handler需要调用Looper.prepare();也有另一种方法就是使用主线程中的Looper,那就不必新建Looper对象了: threadMainLoopHandler =new

Handler(Looper.getMainLooper()){

public void handleMessage(android.os.Message msg) { Log.d(Constant.TAG,

MessageFormat.format("Thread[{0}]--threadMainLoopHandler

handleMessage run...", Thread

.currentThread().getName()));

}

//该handleMessage方法将在mainthread中执行 };

这时候注意不要在handleMessage做太多的操作,因为它在主线程中执行,会影响主线程执行ui更新操作。

使用Message.callback回调

public void dispatchMessage(Message msg) {

if (msg.callback != null) {

handleCallback(msg);

} else {

篇三:Java培训教程-关于Handler的详解

Handler在Android的学习当中应用是非常多的,我们就依次的来解决handler相关问题。其实在handler当中有很多问题比较难理解,比如我们在子线程中通过post的方法发送一条消息,然后就立即能够在handlemessage方法中接受到这条消息,在最初我们学习中都会比较困惑,那么今天我们通过handler的详细讲解,让大家了解handler的机制是什么,并且结合源码和大量的实例让大家更深的了解handler,通过今天的学习,相信大家对handler会有一定的掌握,handler对我们日后android的开发或者面试中都是非常重要的存在。

1. Handler是什么?

在我们学习一门技术和语言之前,一定要先了解以下这门技术和语言是什么,不要盲目的去学习,因为技术太多了,我们要把经历放在核心的技术当中。

Handler在我们android开发当中是一个非常重要的机制,那handler又是什么呢?

handler是android提供用于更新ui的一套机制,也是消息处理的机制。

handler的主要作用有两个:

(1):在新启动的线程中发送信息。

(2):在主线程中获取,处理信息。

2. 为什么要是用handler?

如果我们不用handler去发送消息,更新ui可以么?

是不行的。 Android在设计的时候,就封装了一套消息创建,传递,处理机制,如果不遵循这样的机制,就没有办法更新ui信息的,就会抛出异常信息。

异常的描述:不能在非ui线程中去更新ui。

Only the original thread that created a view hierarchy can touch its views.

3.Handler怎么用呢?

想要了解handler怎么用,就需要去看一下api文档。

一个handler允许你发送和处理message和Runnable对象在相关联的MessageQueen。每个handler实例都与一个单独的线程绑定,该线程带有消息队列MessageQueen。当你创建一个新的handler时,它默认会绑定到创建线程的MessageQueen中,从这一点上,它将传递消息和runnable对象,在MessageQueen中执行这个消息。

磨砺营IT教育版权所有

Handler有两个主要用途:

1.合理调度安排消息和runnable对象,使它们在将来的某个点被执行。

2.将一个动作入队安排在非当前线程执行。

调度消息是通过一系列的post方法和sendMessage方法。

post方法允许你向消息队列中入队一些Runnable对象,在它们被接收到的时候会被调用.

sendMessage方法允许你入队一个消息对象(Message),包含一个bundle数据,之后将会被Handler的handleMessage(Message)方法所处理。

当为应用程序创建一个进程时,它的主线程专门负责运行一个消息队列,它负责管理顶级应用程序对象(活动、广播接收器等),以及它们所创建的任何窗口。您可以创建自己的线程,并通过一个处理程序与主应用程序线程进行通信。这是通过之前调用的post或SendMessage方法从新的线程。给定的runnable对象或消息将被安排在处理程序的消息队列,在适当时候进行处理。

实例一:handler的post基本用法

public class MainActivity extends Activity {

private TextView tv;

private Handler handler = new Handler();

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

tv = (TextView)findViewById(R.id.tv);

new Thread(){

public void run() {

磨砺营IT教育版权所有

try {

Thread.sleep(2000);

handler.post(new Runnable() {

@Override

public void run() {

tv.setText("123456789");

}

});

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}.start();

}

}

实例二:仿照淘宝页面切换图片

布局代码:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"

android:layout_height="match_parent">

<ImageView

磨砺营IT教育版权所有

android:id="@+id/img"

android:layout_width="200dp"

android:layout_height="200dp"

android:layout_centerHorizontal="true"

android:layout_centerVertical="true"

android:src="@drawable/d_xiongmao" />

</RelativeLayout>

java逻辑代码:

package com.qf.handler_demo02;

public class MainActivity extends Activity {

private ImageView img;

private int images[] =

{R.drawable.d_xiongmao,R.drawable.d_xixi,R.drawable.d_xu,R.drawable.d_yinxian};

private int index = 0;

private Handler handler = new Handler();

private MyRunnable runnable = new MyRunnable();

@Override

protected void onCreate(Bundle savedState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

img = (ImageView)findViewById(R.id.img);

//每隔一秒,发送一条runnable对象。

磨砺营IT教育版权所有

handler.postDelayed(runnable, 1000);

}

class MyRunnable implements Runnable{

@Override

public void run() {

index++;

index=index%4;

img.setImageResource(images[index]);

handler.postDelayed(runnable, 1000);

}

}

}

实例三:显示倒计时效果

布局代码:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

android:gravity="center" >

<TextView

android:id="@+id/tv_time"

磨砺营IT教育版权所有


handler机制详解
由:免费论文网互联网用户整理提供,链接地址:
http://m.csmayi.cn/meiwen/28541.html
转载请保留,谢谢!
相关阅读
最近更新
推荐专题