
在AndroID系统中,我们执行完耗时 *** 作都要另外开启子线程来执行,执行完线程以后线程会自动销毁。想象一下如果我们在项目中经常要执行耗时 *** 作,如果经常要开启线程,接着又销毁线程,这无疑是很消耗性能的。
HandlerThread是Google帮我们封装好的,可以用来执行多个耗时 *** 作,而不需要多次开启线程,里面是采用Handler和Looper实现的。
怎么使用?
//创建实例对象,该参数表示线程的名字HandlerThread handlerThread = new HandlerThread("myHandlerThread");//启动我们创建的HandlerThread线程handlerThread.start();//怎样将Handler与线程对象绑定在一起mThreadHandler = new Handler(mHandlerThread.getLooper()) { @OverrIDe public voID handleMessage(Message msg) { checkForUpdate(); if(isUpdate){ mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO); } }};2. 看个实例public class MainActivity extends AppCompatActivity { private static final int MSG_UPDATE_INFO = 0x100; Handler mMainHandler = new Handler(); private TextVIEw mTv; private Handler mThreadHandler; private HandlerThread mHandlerThread; private boolean isUpdate = true; @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.activity_main); mTv = (TextVIEw) findVIEwByID(R.ID.tv); initHandlerThread(); } private voID initHandlerThread() { mHandlerThread = new HandlerThread("xujun"); mHandlerThread.start(); mThreadHandler = new Handler(mHandlerThread.getLooper()){ @OverrIDe public voID handleMessage(Message msg) { checkForUpdate(); if (isUpdate) { mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO); } } }; } /*** 模拟从服务器解析数据*/ private voID checkForUpdate() { try { //模拟耗时 Thread.sleep(1200); mMainHandler.post(new Runnable() { @OverrIDe public voID run() { String result = "实时更新中,当前股票行情:<Fontcolor='red'>%d</Font>"; result = String.format(result, (int) (Math.random() * 5000 + 1000)); mTv.setText(HTML.fromHTML(result)); } }); } catch (InterruptedException e) { e.printstacktrace(); } } @OverrIDe protected voID onResume() { isUpdate = true; super.onResume(); mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO); } @OverrIDe protected voID onPause() { super.onPause(); isUpdate = false; mThreadHandler.removeMessages(MSG_UPDATE_INFO); }@OverrIDe protected voID onDestroy() { super.onDestroy(); mHandlerThread.quit(); mMainHandler.removeCallbacksAndMessages(null); }}运行以上测试代码,将可以看到如下效果图(例子不太恰当,主要使用场景是在handleMessage中执行耗时 *** 作)
基于sdk23的,可以看到,只有一百多行代码:
public class HandlerThread extends Thread { int mPriority; int mTID = -1; Looper mLooper; public HandlerThread(String name) { super(name); mPriority = Process.THREAD_PRIORITY_DEFAulT; } public HandlerThread(String name, int priority) { super(name); mPriority = priority; }/*** Call back method that can be explicitly overrIDden if needed to execute some* setup before Looper loops.*/ protected voID onLooperPrepared() { } @OverrIDe public voID run() { mTID = Process.myTID(); Looper.prepare(); //持有锁机制来获得当前线程的Looper对象 synchronized (this) { mLooper = Looper.myLooper(); //发出通知,当前线程已经创建mLooper对象成功,这里主要是通知getLooper方法中的wait notifyAll(); } //设置线程的优先级别 Process.setThreadPriority(mPriority); //这里默认是空方法的实现,我们可以重写这个方法来做一些线程开始之前的准备,方便扩展 onLooperPrepared(); Looper.loop(); mTID = -1; } public Looper getLooper() { if (!isAlive()) { return null; } // 直到线程创建完Looper之后才能获得Looper对象,Looper未创建成功,阻塞 synchronized (this) { while (isAlive() && mLooper == null) { try { wait(); } catch (InterruptedException e) { } } } return mLooper; } public boolean quit() { Looper looper = getLooper(); if (looper != null) { looper.quit(); return true; } return false; } public boolean quitSafely() { Looper looper = getLooper(); if (looper != null) { looper.quitSafely(); return true; } return false; }/*** Returns the IDentifIEr of this thread. See Process.myTID().*/ public int getThreadID() { return mTID; }}(1)首先看看构造函数
public HandlerThread(String name) { super(name); mPriority = Process.THREAD_PRIORITY_DEFAulT; } public HandlerThread(String name, int priority) { super(name); mPriority = priority; }一个参数的和两个参数的,name代表当前线程的名称,priority为线程的优先级别
(2)看一下run()方法
在run方法里面我们可以看到我们会初始化一个Looper,并设置线程的优先级别
public voID run() { mTID = Process.myTID(); Looper.prepare(); //持有锁机制来获得当前线程的Looper对象 synchronized (this) { mLooper = Looper.myLooper(); //发出通知,当前线程已经创建mLooper对象成功,这里主要是通知getLooper方法中的wait notifyAll(); } //设置线程的优先级别 Process.setThreadPriority(mPriority); //这里默认是空方法的实现,我们可以重写这个方法来做一些线程开始之前的准备,方便扩展 onLooperPrepared(); Looper.loop(); mTID = -1; }前面我们说到使用HandlerThread的时候必须调用 start() 方法,接着才可以将我们的HandlerThread和我们的handler绑定在一起
原因就是我们是在 run() 方法才开始初始化我们的looper,而我们调用HandlerThread的 start() 方法的时候,线程会交给虚拟机调度,由虚拟机自动调用run方法为什么要使用锁机制和 notifyAll() :
原因我们可以从 getLooper() 方法中知道 public Looper getLooper() { if (!isAlive()) { return null; } // 直到线程创建完Looper之后才能获得Looper对象,Looper未创建成功,阻塞 synchronized (this) { while (isAlive() && mLooper == null) { try { wait(); } catch (InterruptedException e) { } } } return mLooper;}总结:在获得mLooper对象的时候存在一个同步的问题,只有当线程创建成功并且Looper对象也创建成功之后才能获得mLooper的值。这里等待方法wait和run方法中的notifyAll方法共同完成同步问题。
(3)接着我们来看一下quit方法和quitSafe方法
public boolean quit() { Looper looper = getLooper(); if (looper != null) { looper.quit(); return true; } return false; } public boolean quitSafely() { Looper looper = getLooper(); if (looper != null) { looper.quitSafely(); return true; } return false; }跟踪这两个方法容易知道只两个方法最终都会调用MessageQueue的 quit(boolean safe) 方法
voID quit(boolean safe) { if (!mQuitAllowed) { throw new IllegalStateException("Main thread not allowedto quit."); } synchronized (this) { if (mQuitting) { return; } mQuitting = true; //安全退出调用这个方法 if (safe) { removeAllFutureMessagesLocked(); } else {//不安全退出调用这个方法 removeAllMessagesLocked(); } // We can assume mPtr != 0 because mQuitting was prevIoUsly false. nativeWake(mPtr); }}不安全的会调用 removeAllMessagesLocked(); ,我们来看这个方法是怎样处理的,其实就是遍历Message链表,移除所有信息的回调,并重置为null。
private voID removeAllMessagesLocked() { Message p = mMessages; while (p != null) { Message n = p.next; p.recycleUnchecked(); p = n; } mMessages = null;}安全地会调用 removeAllFutureMessagesLocked(); 这个方法,它会根据Message.when这个属性,判断我们当前消息队列是否正在处理消息,没有正在处理消息的话,直接移除所有回调,正在处理的话,等待该消息处理处理完毕再退出该循环。因此说 quitSafe() 是安全的,而 quit() 方法是不安全的,因为quit方法不管是否正在处理消息,直接移除所有回调
private voID removeAllFutureMessagesLocked() { final long Now = SystemClock.uptimeMillis(); Message p = mMessages; if (p != null) { //判断当前队列中的消息是否正在处理这个消息,没有的话,直接移除所有回调 if (p.when > Now) { removeAllMessagesLocked(); } else { //正在处理的话,等待该消息处理处理完毕再退出该循环 Message n; for (;;) { n = p.next; if (n == null) { return; } if (n.when > Now) { break; } p = n; } p.next = null; do { p = n; n = p.next; p.recycleUnchecked(); } while (n != null); } }} 总结 以上是内存溢出为你收集整理的Android——HandlerThread浅析全部内容,希望文章能够帮你解决Android——HandlerThread浅析所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)