今日私が紹介する記事は、サンプルコードを通じて Android での HandlerThread の使用法と手順を分析するものです。必要な方は参考にしてください。
HandlerThread の概要:
Thread スレッドが時間のかかるタスクを完了すると、スレッドは 1 回限りの消費者向け製品であることがわかっています。この時点で別の時間のかかるタスクを実行する必要がある場合は、時間のかかるタスクを実行するためにスレッドを再作成する必要があります。ただし、パフォーマンスの問題があります。スレッドの作成と破棄を複数回行うと、システム リソースが消費されます。この問題を理解するために、ループ スレッド Looper Thread を自分で構築することができます。ループ スレッドに時間のかかるタスクが配置されると、そのスレッドは時間のかかるタスクを実行します。実行後、ループ スレッドは待機状態になります。次の時間のかかるタスクが投入されるまで、この状態になります。このようにして、Thread スレッドを複数回作成することによって発生するパフォーマンスの問題が回避されます。ループ スレッドを自分で構築することもできるかもしれませんが、実際には Aandroid SDK にループ スレッド フレームワークがあると言えます
。この時点で必要なのは、使い方をマスターするだけです。もちろん、今日の主役は HandlerThread です。次に、HandlerThread を起動します。拍手~~
HandlerThread の親クラスは Thread なので、HandlerThread は実際にはスレッドですが、内部的に Looper ループを実装するのに役立つだけです。それでは、
まずハンドラーの使い方を理解しましょう!
HandlerThread の使用手順:
1. インスタンス オブジェクトを作成しますHandlerThread handlerThread = new HandlerThread("handlerThread");
上記のパラメータの主な機能は、現在のスレッドの名前をマークすることです。
handlerThread.start();
Handler subHandler = new Handler(handlerThread.getLooper(), new Handler.Callback() { @Override public boolean handleMessage(Message msg) { //实现自己的消息处理 return true; } });
3 番目のステップは、Handler オブジェクトを作成し、上記の HandlerThread のルーパー オブジェクトを Handler パラメーターとして使用し、その後 Handler の
メッセージ送信
の形式で、時間のかかるタスクをスレッド
HandlerThread に送信できます。これは、subHandler の Callback インターフェイス クラスの handlerMessage メソッドが実際にワーカー スレッドで実行されることを意味します。
HandlerThreadインスタンス:
package com.example.handlerthread; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity { private Handler mSubHandler; private TextView textView; private Button button; private Handler.Callback mSubCallback = new Handler.Callback() { //该接口的实现就是处理异步耗时任务的,因此该方法执行在子线程中 @Override public boolean handleMessage(Message msg) { switch (msg.what) { case 0: Message msg1 = new Message(); msg1.what = 0; msg1.obj = java.lang.System.currentTimeMillis(); mUIHandler.sendMessage(msg1); break; default: break; } return false; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView) findViewById(R.id.textView); button = (Button) findViewById(R.id.button); HandlerThread workHandle = new HandlerThread("workHandleThread"); workHandle.start(); mSubHandler = new Handler(workHandle.getLooper(), mSubCallback); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //投放异步耗时任务到HandlerThread中 mSubHandler.sendEmptyMessage(0); } }); } }
HandlerThread
構築メソッド/** * Handy class for starting a new thread that has a looper. The looper can then be * used to create handler classes. Note that start() must still be called. */ public class HandlerThread extends Thread { //线程优先级 int mPriority; //当前线程id int mTid = -1; //当前线程持有的Looper对象 Looper mLooper; //构造方法 public HandlerThread(String name) { //调用父类默认的方法创建线程 super(name); mPriority = Process.THREAD_PRIORITY_DEFAULT; } //带优先级参数的构造方法 public HandlerThread(String name, int priority) { super(name); mPriority = priority; } ............... }
HandlerThrad の run メソッド
public class HandlerThread extends Thread { /** * Call back method that can be explicitly overridden if needed to execute some * setup before Looper loops. */ protected void onLooperPrepared() { } @Override public void run() { //获得当前线程的id mTid = Process.myTid(); //准备循环条件 Looper.prepare(); //持有锁机制来获得当前线程的Looper对象 synchronized (this) { mLooper = Looper.myLooper(); //发出通知,当前线程已经创建mLooper对象成功,这里主要是通知getLooper方法中的wait notifyAll(); } //设置当前线程的优先级 Process.setThreadPriority(mPriority); //该方法实现体是空的,子类可以实现该方法,作用就是在线程循环之前做一些准备工作,当然子类也可以不实现。 onLooperPrepared(); //启动loop Looper.loop(); mTid = -1; } }
getLooper は、現在のスレッドの Looper オブジェクトを取得します
/** * This method returns the Looper associated with this thread. If this thread not been started * or for any reason is isAlive() returns false, this method will return null. If this thread * has been started, this method will block until the looper has been initialized. * @return The looper. */ public Looper getLooper() { //如果线程不是存活的,则直接返回null if (!isAlive()) { return null; } // If the thread has been started, wait until the looper has been created. //如果线程已经启动,但是Looper还未创建的话,就等待,知道Looper创建成功 synchronized (this) { while (isAlive() && mLooper == null) { try { wait(); } catch (InterruptedException e) { } } } return mLooper; }
分析: 実際、メソッドの先頭にある英語のコメントで非常に明確に説明されています。このメソッドの機能は、スレッド内の現在の HandlerThread mLooper オブジェクトを取得することです。
まず現在のスレッドが生きているかどうかを確認し、生きていない場合は直接 null を返します。次に、現在のスレッドが存続している場合は、スレッドのメンバー変数 mLooper が null であるかどうかを確認します。
null の場合は、現在のスレッドは正常に作成されましたが、Looper オブジェクトを作成する時間がなかったことを意味します。 runメソッドのnotifyAllメソッドが呼び出された後、現在のスレッドのwaitメソッドに終了を待つように通知し、ループから抜け出し、mLooperの値を取得します。物体。
总结:在获得mLooper对象的时候存在一个同步的问题,只有当线程创建成功并且Looper对象也创建成功之后才能获得mLooper的值。这里等待方法wait和run方法中的notifyAll方法共同完成同步问题。
quit结束当前线程的循环
/** * Quits the handler thread's looper. * <p> * Causes the handler thread's looper to terminate without processing any * more messages in the message queue. * </p><p> * Any attempt to post messages to the queue after the looper is asked to quit will fail. * For example, the {@link Handler#sendMessage(Message)} method will return false. * </p><p class="note"> * Using this method may be unsafe because some messages may not be delivered * before the looper terminates. Consider using {@link #quitSafely} instead to ensure * that all pending work is completed in an orderly manner. * </p> * * @return True if the looper looper has been asked to quit or false if the * thread had not yet started running. * * @see #quitSafely */ 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; }
分析:以上有两种让当前线程退出循环的方法,一种是安全的,一中是不安全的。至于两者有什么区别? quitSafely方法效率比quit方法标率低一点,但是安全。具体选择哪种就要看具体项目了。
总结:
1.HandlerThread适用于构建循环线程。
2.在创建Handler作为HandlerThread线程消息执行者的时候必须调用start方法之后,因为创建Handler需要的Looper参数是从HandlerThread类中获得,而Looper对象的赋值又是在HandlerThread的run方法中创建。
相信看了这些案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
相关阅读:
以上がHandlerThread ソース コードの詳細な Android 例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。