Android线程 - HandlerThread
2017-09-16 16:44
84 查看
概述
HandlerThread就是可以处理消息循环的线程,它是一个拥有Looper的线程,可以处理消息循环。简单理解就是一个Thread,内部使用了Looper。
我们都知道,除了在主线程,其他线程必须通过Looper.prepare()创建Looper、Looper.loop()开启消息循环。
举个栗子:
我的天,在Handler更新UI,出现如下异常。
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
提示只有创建视图(主线程)的线程才能更新UI。mChildThreadHandler是在子线程中开启消息循环,所以没办法切换到主线程中更新UI。
HandlerThread就是在Thread中开启消息循环,但为什么要使用HandlerThread呢?当把Looper转到子线程处理,可以减轻主线程的工作量,使主界面更流畅。
再举一个栗子
用一个Handler更新UI,另一个Handler用于异步耗时任务
布局这里就不贴了,就一个Button一个TextView
效果
HandlerThread源码
HandlerThread是一个Thread,传入的参数就是该线程的名称。
重点3、4通过内部自己创建Looper,开启消息循环,会一直循环,当明确不需要的时候,要记得销毁。
5、6的两个方法分别的作用为:
Looper的quit():将MessageQueue消息池的消息全部清空,无论是延迟消息还是非延迟消息。
Looper的quitSafely():只会清空MessageQueue消息池中所有的延迟消息,那些非延迟的消息会发给Handler去处理。
Looper的quit方法从API Level 1就存在了,但是Looper的quitSafely方法从API Level 18才添加进来。
再次强调:HandlerThread是串行执行,拥有自己的消息队列,不会阻塞UI线程。
HandlerThread就是可以处理消息循环的线程,它是一个拥有Looper的线程,可以处理消息循环。简单理解就是一个Thread,内部使用了Looper。
我们都知道,除了在主线程,其他线程必须通过Looper.prepare()创建Looper、Looper.loop()开启消息循环。
举个栗子:
import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; public class MainActivity extends AppCompatActivity { private Button mBtnStart; private Handler mChildThreadHandler; //子线程的Handler @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Thread thread = new ChildThread(); thread.start(); mBtnStart = (Button)findViewById(R.id.btn_start); mBtnStart.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mChildThreadHandler.sendEmptyMessage(0); } }); } class ChildThread extends Thread{ @Override public void run(){ Looper.prepare(); //给线程创建一个消息循环 mChildThreadHandler = new Handler(){ @Override public void handleMessage(Message msg){ super.handleMessage(msg); mBtnStart.setText("更新按钮文本"); } }; Looper.loop(); //开始消息循环 } } }
我的天,在Handler更新UI,出现如下异常。
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
提示只有创建视图(主线程)的线程才能更新UI。mChildThreadHandler是在子线程中开启消息循环,所以没办法切换到主线程中更新UI。
HandlerThread就是在Thread中开启消息循环,但为什么要使用HandlerThread呢?当把Looper转到子线程处理,可以减轻主线程的工作量,使主界面更流畅。
再举一个栗子
用一个Handler更新UI,另一个Handler用于异步耗时任务
布局这里就不贴了,就一个Button一个TextView
import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private Button mBtnStart; private TextView mTvShow; private Handler mChildHandler; //子线程的Handler private HandlerThread mHandlerThread; //创建异步HandlerThread private int flag; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTvShow = (TextView)findViewById(R.id.tv_show); mBtnStart = (Button)findViewById(R.id.btn_start); mBtnStart.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mChildHandler.sendEmptyMessage(0); } }); mHandlerThread = new HandlerThread("handlerThread"); mHandlerThread.start(); mChildHandler = new Handler(mHandlerThread.getLooper(), new Handler.Callback() { @Override public boolean handleMessage(Message message) { //这里执行耗时操作后 更新UI Message msg = Message.obtain(); msg.arg1 = ++flag; msg.what = 0; mUpdateUIHandler.sendMessage(msg); return true; } }); } private Handler mUpdateUIHandler = new Handler(){ @Override public void handleMessage(Message message){ //这里用于更新UI switch (message.what){ case 0: mTvShow.setText("得到的数据"+message.arg1); break; } } }; @Override protected void onDestroy() { super.onDestroy(); mHandlerThread.quit(); } }
效果
HandlerThread源码
public class More ...HandlerThread extends Thread { int mPriority; int mTid = - ; Looper mLooper; public More ...HandlerThread(String name) { //重点1 super(name); mPriority = Process.THREAD_PRIORITY_DEFAULT; } public More ...HandlerThread(String name, int priority) { super(name); mPriority = priority; } protected void More ...onLooperPrepared() { } @Override public void More ...run() { //重点2 mTid = Process.myTid(); Looper.prepare(); //重点3 synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } Process.setThreadPriority(mPriority); onLooperPrepared(); Looper.loop(); //重点4 mTid = - ; } public Looper More ...getLooper() { if (!isAlive()) { return null; } synchronized (this) { while (isAlive() && mLooper == null) { try { wait(); } catch (InterruptedException e) { } } } return mLooper; } public boolean More ...quit() { //重点5 Looper looper = getLooper(); if (looper != null) { looper.quit(); return true; } return false; } public boolean More ...quitSafely() { //重点6 Looper looper = getLooper(); if (looper != null) { looper.quitSafely(); return true; } return false; } public int More ...getThreadId() { return mTid; } }
HandlerThread是一个Thread,传入的参数就是该线程的名称。
重点3、4通过内部自己创建Looper,开启消息循环,会一直循环,当明确不需要的时候,要记得销毁。
5、6的两个方法分别的作用为:
Looper的quit():将MessageQueue消息池的消息全部清空,无论是延迟消息还是非延迟消息。
Looper的quitSafely():只会清空MessageQueue消息池中所有的延迟消息,那些非延迟的消息会发给Handler去处理。
Looper的quit方法从API Level 1就存在了,但是Looper的quitSafely方法从API Level 18才添加进来。
再次强调:HandlerThread是串行执行,拥有自己的消息队列,不会阻塞UI线程。
相关文章推荐
- Android线程和线程池(二)--HandlerThread
- android线程使用完毕后,记得关闭
- Android中文API(128) —— HandlerThread
- HandlerThread实现真正的异步的简单实例,用到了Bundle对象
- HandlerThread
- HandlerThread
- 终止Android中HandlerThread的方法
- 浅析Android线程模型一
- Android温习:Looper.loop() android线程中的消息循环
- 深入Android线程的相关问题解惑
- HandlerThread
- Handler+Thread和HandlerThread的用法比较
- 关于使用HandlerThread获取数据,并实现sqlite分页。
- HandlerThread的 使用
- Android线程
- Android线程与进程(二)线程详解
- HandlerThread的 使用
- HandlerThread的使用
- android耗时任务_HandlerThread
- Thread与HandlerThread