android looper定义,Android中的Looper的使用

66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

什么是LooperLooper用来把一个线程封装成Looper线程,因为新new出来的线程不是Looper线程.

那么Looper线程有什么用呢,简单的讲,Looper线程可以接收其他线程发送的消息,并进行处理.

在打造Looper线程之前,先学习一下Looper的API,主要有一下几个方法public static void prepare() 为当前线程提供一个Looper

public static void loop() 在线程中执行消息队列,在结束时通过调用looper.quit()

public Thread getThread() 返回和looper相关联的线程

public static Looper getMainLooper() 返回当前应用程序中依赖主线程的looper

public static Looper myLooper() 返回和当前线程关联的looper,如果没有looper与当前线程关联,则返回null

public static MessageQueue myQueue() 返回和当前线程相关联的消息队列,使用这个方法,必须确保当前线程与looper相关联

public static void prepareMainLooper() 初始化与主线程相关联的looper

Looper的工作原理

看图说话:

looper%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%861.png

这里简单的描述一下 Looper线程中维护了唯一一个Looper对象,Looper对象中有一个MessageQueue(消息队列),这个是一个存放Message的队列.当有消息来的时候,就添加到MessageQueue中去.而Message是Handler发送的,这个Message对象中有由哪个handler发送它的引用,假如 MS1是Handler1发送的那么MS1中的target就引用Handler1.

当调用loop()方法之后,这个Loopper线程就真正的开始工作了,不断的从自己的MessageQueue中取出Message,然后处理

从上图中,我们可以发现 Looper Thread中只有一个Looper,可以有多个Handler.

什么情况下使用 Looper 线程

如果我们需要新建一个线程,并且这个线程要能够循环处理其他线程发来的消息事件,或者需要长期与其他线程进行复杂的交互,这时就需要用到Looper来给线程建立消息队列。

如何打造一个 Looper 线程1

2

3

4

5

6

7

8

9

10

11

12public class extends Thread{

public void run(){

Looper.prepare();

// ...异步执行的代码,实例化handler

// 开始循环处理消息队列

Looper.loop();

}

}

这样一个非常简单的Looper线程就打造好了.那么怎么接受其他线程发送的消息?

下面通过一个主线程向子线程发送消息的例子说明1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96package com.zhou.dell.dtest041101_statusbar;

import android.app.Activity;

import android.os.Bundle;

import android.os.Handler;

import android.os.Looper;

import android.os.Message;

import android.util.Log;

import android.view.View;

import android.widget.Button;

/**

* author:zhou

* version:v1.0

* date: 2016/4/12

* description: 通过主线程向子线程发送消息

*/

public class TestActivity extends Activity{

private String TAG = TestActivity.class.getSimpleName();

private int sendCount = 0; // 发送次数

private LooperThread looperThread;

protected void onCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);

// 开启线程

looperThread = new LooperThread();

looperThread.start();

Button bt = new Button(this);

bt.setText("点击我,从主线程发送到子线程消息");

bt.setOnClickListener(new View.OnClickListener() {

public void onClick(View view){

Message message = Message.obtain();

message.arg1 = sendCount++;

Log.d(TAG, "发送的handler的信息: " + looperThread.getmHandler().toString());

looperThread.getmHandler().sendMessage(message);

}

});

setContentView(bt);

}

/**

当Activity 销毁时

*/

public void onDestroy(){

super.onDestroy();

looperThread.exit();

looperThread = null;

}

class extends Thread{

private String TAG = LooperThread.class.getSimpleName();

private Handler mHandler;

private Looper mLooper;

public (){

super();

}

public void run(){

super.run();

Looper.prepare();

mLooper = Looper.myLooper();

//Handler如果不带参数的默认构造函数:new Handler(),

//实际上是通Looper.myLooper()来获取当前线程中的消息循环,

mHandler = new Handler(mLooper) {

@Override

public void handleMessage(Message msg){

super.handleMessage(msg);

Log.d(TAG, "接收到的消息中的target对象的信息: " + msg.getTarget());

Log.d(TAG, "接受发送的内容" + msg.arg1);

}

};

// 开始轮寻

Looper.loop();

}

public Handler getmHandler(){

return mHandler;

}

public void exit(){

if (mLooper != null) {

mLooper.quit();

mLooper = null;

}

}

}

}

运行之后点击按钮,打印出来的日志如下

04-12 20:27:15.172 11994-11994/com.zhou.dell.dtest041101_statusbar D/ViewRootImpl: ViewPostImeInputStage ACTION_DOWN

04-12 20:27:15.262 11994-11994/com.zhou.dell.dtest041101_statusbar D/TestActivity: 发送的handler的信息: Handler (com.zhou.dell.dtest041101_statusbar.TestActivity$LooperThread$1) {3bf99b43}

04-12 20:27:15.262 11994-12038/com.zhou.dell.dtest041101_statusbar D/LooperThread: 接收到的消息中的target对象的信息: Handler (com.zhou.dell.dtest041101_statusbar.TestActivity$LooperThread$1) {3bf99b43}

04-12 20:27:15.262 11994-12038/com.zhou.dell.dtest041101_statusbar D/LooperThread: 接受发送的内容0

可以发现2点:发送和处理的handler是同一个,

子线程确实接受了从主线程中发送的消息

总结

Android的Looper类使用的5个要点:Looper类用来为一个线程开启一个消息循环。

默认情况下android中新诞生的线程是没有开启消息循环的。(主线程除外,主线程系统会自动为其创建Looper对象,开启消息循环。)

Looper对象通过MessageQueue来存放消息。一个线程只能有一个Looper,对应一个MessageQueue。

通常是通过Handler对象来与Looper进行交互的。Handler可看做是Looper的一个接口,用来向指定的Looper发送消息及定义处理方法。

默认情况下Handler会与其被定义时所在线程的Looper绑定,比如,Handler在主线程中定义,那么它是与主线程的Looper绑定。

mainHandler = new Handler() 等价于new Handler(Looper.myLooper()).

Looper.myLooper():获取当前进程的looper对象,类似的 Looper.getMainLooper() 用于获取主线程的Looper对象。

在非主线程中直接new Handler() 会报如下的错误:

E/AndroidRuntime( 6173): Uncaught handler: thread Thread-8 exiting due to uncaught exception

E/AndroidRuntime( 6173): java.lang.RuntimeException: Can’t create handler inside thread that has not called Looper.prepare()

原因是非主线程中默认没有创建Looper对象,需要先调用Looper.prepare()启用Looper。

Looper.loop(); 让Looper开始工作,从消息队列里取消息,处理消息。

注意:写在Looper.loop()之后的代码不会被执行,这个函数内部应该是一个循环,当调用mHandler.getLooper().quit()后,loop才会中止,其后的代码才能得以运行。

基于以上知识,可实现主线程给子线程(非主线程)发送消息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值