Android -- Looper.prepare()和Looper.loop() —深度版
Android中的Looper类,是用来封装消息循环和消息队列的一个类,用于在android线程中进行消息处理。handler事实上能够看做是一个工具类。用来向消息队列中插入消息的。
(1) Looper类用来为一个线程开启一个消息循环。
默认情况下android中新诞生的线程是没有开启消息循环的。(主线程除外,主线程系统会自己主动为其创建Looper对象,开启消息循环。) Looper对象通过MessageQueue来存放消息和事件。
一个线程仅仅能有一个Looper。相应一个MessageQueue。
(2) 一般是通过Handler对象来与Looper进行交互的。
Handler可看做是Looper的一个接口。用来向指定的Looper发送消息及定义处理方法。 默认情况下Handler会与其被定义时所在线程的Looper绑定,比方,Handler在主线程中定义。那么它是与主线程的Looper绑定。
mainHandler = new Handler() 等价于new Handler(Looper.myLooper()). Looper.myLooper():获取当前进程的looper对象,类似的 Looper.getMainLooper() 用于获取主线程的Looper对象。
(3) 在非主线程中直接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。
(4) Looper.loop(); 让Looper開始工作,从消息队列里取消息,处理消息。
注意:写在Looper.loop()之后的代码不会被执行,这个函数内部应该是一个循环,当调用mHandler.getLooper().quit()后。loop才会中止,其后的代码才干得以执行。
(5) 基于以上知识,可实现主线程给子线程(非主线程)发送消息。
把以下样例中的mHandler声明成类成员,在主线程通过mHandler发送消息就可以。
Android官方文档中Looper的介绍: Class used to run a message loop for a thread. Threads by default do not have a message loop
associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.
Most interaction with a message loop is through the Handler class.
This is a typical example of the implementation of a Looper thread, using the separation of prepare() and loop() to create an initial Handler
to communicate with the Looper.
class LooperThread extends Thread
{
public Handler mHandler;
public void run()
{
Looper.prepare();
mHandler = new Handler()
{
public void handleMessage(Message msg)
{
// process incoming messages here
}
};
Looper.loop();
}
假设线程中使用Looper.prepare()和Looper.loop()创建了消息队列就能够让消息处理在该线程中完毕。
android HandlerThread使用小例
之前研究过handler 和 looper 消息队列。只是android里的handler不是另外开启线程来运行的。还是在主UI线程中,假设想另启线程的话须要用到HandlerThread来实现。在使用HandlerThread的时候须要实现CallBack接口以重写handlerMessage方法。在handlerMessage方法中来处理自己的逻辑。
下来给出一个小样例程序。
layout文件非常easy,就一个button来启动HanlderTread线程
<?xml version="1.0" encoding="utf-8"? >
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" > <TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" /> <Button
android:id="@+id/handlerThreadBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="startHandlerThread" /> </LinearLayout>
Activity代码例如以下:
package com.tayue; import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.HandlerThread;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
/**
*
* @author xionglei
*
*/
public class TestHandlerActivity extends Activity implements OnClickListener{ public Button handlerThreadBTN;
MyHandlerThread handlerThread;
Handler handler; /** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//打印UI线程的名称
System.out.println("onCreate CurrentThread = " + Thread.currentThread().getName()); setContentView(R.layout.main); handlerThreadBTN = (Button) findViewById(R.id.handlerThreadBtn);
handlerThreadBTN.setOnClickListener(this); handlerThread = new MyHandlerThread("myHanler");
handlerThread.start();
//注意: 这里必须用到handler的这个构造器,由于须要把callback传进去,从而使自己的HandlerThread的handlerMessage来替换掉Handler原生的handlerThread
handler = new Handler(handlerThread.getLooper(), handlerThread);
} @Override
public void onClick(View v) {
//点击button后来开启线程
handler.sendEmptyMessage(1);
} private class MyHandlerThread extends HandlerThread implements Callback { public MyHandlerThread(String name) {
super(name);
} @Override
public boolean handleMessage(Message msg) {
//打印线程的名称
System.out.println(" handleMessage CurrentThread = " + Thread.currentThread().getName());
return true;
}
}
}
点击button。打印的日志例如以下(这里点击了3次) 07-06 09:32:48.776: I/System.out(780): onCreate CurrentThread = main 07-06 09:32:55.076: I/System.out(780): handleMessage CurrentThread = myHanler 07-06 09:32:58.669: I/System.out(780): handleMessage CurrentThread = myHanler 07-06 09:33:03.476:
I/System.out(780): handleMessage CurrentThread = myHanler
HandlerThread就这么简单。
当然 android自己也有异步线程的handler,就是AsyncTask。这个类就是封装了HandlerThread 和handler来实现异步多线程的操作的。
相同能够这样使用:
private boolean iscancel = false; //用户手动取消登录的标志位
handlerThread = new HandlerThread("myHandlerThread");
handlerThread.start();
handler = new MyHandler(handlerThread.getLooper());
// 将要运行的线程对象加入到线程队列中
handler.post(new Runnable() {
@Override
public void run() {
Message message = handler.obtainMessage();
UserBean user = Bbs.getInstance().Login(username, password);//耗时任务
Bundle b = new Bundle();
b.putSerializable("user", user);
message.setData(b);
message.sendToTarget(); //或使用 handler.sendMessage(message);
}
});
class MyHandler extends Handler {
public MyHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
if(iscancel == false){
// 操作UI线程的代码
Bundle b = msg.getData();
UserBean user = (UserBean)b.get("user");
......
}
}
}
Android -- Looper.prepare()和Looper.loop() —深度版的更多相关文章
- Android -- Looper.prepare()和Looper.loop() —深入版
Android中的Looper类,是用来封装消息循环和消息队列的一个类,用于在android线程中进行消息处理.handler其实可以看做是一个工具类,用来向消息队列中插入消息的. (1) Loope ...
- 【转】Android -- Looper.prepare()和Looper.loop()
Looper.prepare()和Looper.loop() 原文地址:http://blog.csdn.net/heng615975867/article/details/9194219 Andro ...
- Looper.prepare()和Looper.loop()
什么时候需要 Looper Looper用于封装了android线程中的消息循环,默认情况下一个线程是不存在消息循环(message loop)的,需要调用Looper.prepare()来给线程创建 ...
- Android 线程 Looper.prepare()、Looper.loop() 使用
优化项目过程中发现了一个非常Low的问题,整理一下.备忘: 说问题之前先看下HandlerThread的定义 一个封装了looper的线程: Looper用于封装了android线程中的消息循环. ...
- Android handler 报错处理Can't create handler inside thread that has not called Looper.prepare()
问题: 写了一个sdk给其他人用,提供一个回调函数,函数使用了handler处理消息 // handler监听网络请求,完成后操作回调函数 final Handler trigerGfHandler ...
- Android进阶(十六)子线程调用Toast报Can't create handler inside thread that has not called Looper.prepare() 错误
原子线程调用Toast报Can't create handler inside thread that has not called Looper.prepare() 错误 今天用子线程调Toast报 ...
- ThreadLocal ——android消息机制handler在非主线程创建not called Looper.prepare() 错误的原因
引用自:https://www.jianshu.com/p/a8fa72e708d3 引出: 使用Handler的时候,其必须要跟一个Looper绑定.在UI线程可直接初始化Handler来使用.但是 ...
- android 37 线程通信Looper
安卓程序的主线程也叫UI线程. 工作线程和主线程的差别:安卓主线程已经调用了Looper.prepare()方法了,已经有一个MessageQueue对象了,所以才可以在工作线程用Handler发消息 ...
- 「Android」消息驱动Looper和Handler类分析
Android系统中的消息驱动工作原理: 1.有一个消息队列,可以往这个消息队列中投递消息; 2.有一个消息循环,不断的从消息队列中取得消息,然后处理. 工作流程: 1.事件源将待处理的消息加入到消息 ...
随机推荐
- git digest
.gitignore文件示例: .classpath .project .idea/ .settings/ target/ *~ *.iml *.log *.tmp https://zhuanlan. ...
- ANSI Common Lisp 中文翻譯版 — ANSI Common Lisp 中文版
ANSI Common Lisp 中文翻譯版 — ANSI Common Lisp 中文版 ANSI Common Lisp 中文翻譯版¶
- 公布windows的"Universal Apps" Unity3D游戏
转载请注明出处:http://blog.csdn.net/u010019717 更全的内容请看我的游戏蛮牛地址:http://www.unitymanual.com/space-uid-18602.h ...
- 《Effective C++ 》学习笔记——条款02
**************************** 一. Accustoming Yourself to C++ **************************** 条款02: Pref ...
- java Quartz定时器任务与Spring task定时的几种实现,
java Quartz定时器任务与Spring task定时的几种实现 基于java 的定时任务实现, Quartz 时间详细配置 请查阅 http://www.cnblogs.com/si ...
- 一个linux常见命令的列表
这是一个linux常见命令的列表. 那些有• 标记的条目,你可以直接拷贝到终端上而不需要任何修改,因此你最好开一个终端边读边剪切&拷贝. 所有的命令已在Fedora和Ubuntu下做了测试 命 ...
- 【Android UI】案例03滑动切换效果的实现(ViewPager)
本例使用ViewPager实现滑动切换的效果.本例涉及的ViewPager.为android.support.v4.view.ViewPager.所以须要在android项目中导入android-su ...
- JS创建 trim() 方法,此方法在IE7、IE8中不存在 需要自定义
function trim(str){ //创建空格对象 var space = new String(" "); /* str = trimLeft(str,space); st ...
- 运行一个android程序,直接访问某个网站
package android.com.youtube; import android.app.Activity; import android.content.Intent; import andr ...
- 黄聪:Microsoft Enterprise Library 5.0 系列教程(三) Validation Application Block (初级)
原文:黄聪:Microsoft Enterprise Library 5.0 系列教程(三) Validation Application Block (初级) 企业库提供了一个很强大的验证应用程序模 ...