HandlerThread ソース コードの詳細な Android 例

php中世界最好的语言
リリース: 2023-03-18 06:22:01
オリジナル
1606 人が閲覧しました

今日私が紹介する記事は、サンプルコードを通じて Android での HandlerThread の使用法と手順を分析するものです。必要な方は参考にしてください。

HandlerThread の概要:
Thread スレッドが時間のかかるタスクを完了すると、スレッドは 1 回限りの消費者向け製品であることがわかっています。この時点で別の時間のかかるタスクを実行する必要がある場合は、時間のかかるタスクを実行するためにスレッドを再作成する必要があります。ただし、パフォーマンスの問題があります。スレッドの作成と破棄を複数回行うと、システム リソースが消費されます。この問題を理解するために、ループ スレッド Looper Thread を自分で構築することができます。ループ スレッドに時間のかかるタスクが配置されると、そのスレッドは時間のかかるタスクを実行します。実行後、ループ スレッドは待機状態になります。次の時間のかかるタスクが投入されるまで、この状態になります。このようにして、Thread スレッドを複数回作成することによって発生するパフォーマンスの問題が回避されます。ループ スレッドを自分で構築することもできるかもしれませんが、実際には Aandroid SDK にループ スレッド フレームワークがあると言えます

。この時点で必要なのは、使い方をマスターするだけです。もちろん、今日の主役は HandlerThread です。次に、HandlerThread を起動します。拍手~~

HandlerThread の親クラスは Thread なので、HandlerThread は実際にはスレッドですが、内部的に Looper ループを実装するのに役立つだけです。それでは、

まずハンドラーの使い方を理解しましょう!

HandlerThread の使用手順:

1. インスタンス オブジェクトを作成します

HandlerThread handlerThread = new HandlerThread("handlerThread");
ログイン後にコピー

上記のパラメータの主な機能は、現在のスレッドの名前をマークすることです。

2. HandlerThread スレッドを開始します

handlerThread.start();
ログイン後にコピー


この時点で、ループ スレッドの構築が完了しました。そこで、時間のかかる非同期タスクを HandlerThread スレッドに入れて実行するにはどうすればよいのかと疑問に思われるかもしれません。もちろん方法はあります。第 3 部を見てみましょう。

3. ループメッセージ処理メカニズムを構築する

Handler subHandler = new Handler(handlerThread.getLooper(), new Handler.Callback() {
      @Override
      public boolean handleMessage(Message msg) {
        //实现自己的消息处理
        return true;
      }
    });
ログイン後にコピー

3 番目のステップは、Handler オブジェクトを作成し、上記の HandlerThread のルーパー オブジェクトを Handler パラメーターとして使用し、その後 Handler の

handlerMessage メソッドを書き換えることです。コールバック インターフェイス クラス。時間のかかるタスクに取り組みます。

要約: 上記の 3 つのステップの順序を間違えてはならず、厳密に従う必要があります。この時点で、subHandler を呼び出して、実行のための

メッセージ送信

の形式で、時間のかかるタスクをスレッド


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のソースコード分析

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;
  }
...............
}
ログイン後にコピー



分析: このクラスは、最初に説明を示します: このクラスは使用されますオペラを作成するにはループするスレッドの場合、Handler オブジェクトを作成するために Looper オブジェクトが使用されます。Handler

オブジェクトを作成する前に、start() メソッドを呼び出してスレッドを開始する必要があることに注意してください。ここで質問がある人もいるかもしれません?ハンドラーを作成する前に start() メソッドを呼び出す必要があるのはなぜですか?これについては後でお答えします。

上記のコードのコメントは非常に明確です。HandlerThread クラスには 2 つのコンストラクターがあります。違いは、現在のスレッドの優先順位パラメーターを設定することです。自分の状況に応じて優先度

を設定することも、デフォルトの優先度を使用することもできます。


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;
  }
}
ログイン後にコピー

分析: 上記のコードのコメントは非常に明確に記述されています。上記の run メソッドの主な機能は、ループ スレッドを構築するために Looper.prepare と Looper.loop を呼び出すことです。 onLooperPrepared メソッドは run メソッドでループを開始する前に呼び出され、このメソッドの実装は空であり、ユーザーはこのメソッドをサブクラスに実装できることに注意してください。このメソッドの目的は、スレッド ループの前に初期化作業を行うことです。もちろん、必要に応じて、このメソッドを実装する必要はありません。また、Google のエンジニアはコードを記述する際にコードのスケーラビリティも考慮していることがわかります。素晴らしい!

HandlerThread の他のメソッド

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&#39;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中文网其它相关文章!

相关阅读:

php如何实现栈数据结构以及括号匹配算法的代码示例详解

php中最简单的字符串匹配算法,php匹配算法_PHP教程

最简单的php中字符串匹配算法教程

以上がHandlerThread ソース コードの詳細な Android 例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート