软件编程
位置:首页>> 软件编程>> Android编程>> Android HandlerThread案例详解

Android HandlerThread案例详解

作者:tandeneck  发布时间:2022-04-20 09:46:25 

标签:Android,HandlerThread

HandlerThread 顾名思义就是一种可以使用 Handler 的 Thread。日常开发中我们经常会通过创建一个 Thread 去执行任务,有多个任务就多创建几个线程实现,这时候可能出现线程同步的问题。不过有时候我们并不需要很强的并发性,只需保证按照顺序地执行各个任务即可,有什么好办法实现呢?第一反应想到的可能是通过 Executors.newSingleThreadExecutor() 方法来创建一个 SingleThreadExecutor,来统一所有的任务到一个线程中,然后按顺序执行。其实,除了这个方法之外,HandlerThread 也可以实现。

简单使用

首先创建一个 HandlerThreadActivity


public class HandlerThreadActivity extends BaseActivity {

private static final String TAG = "HandlerThreadActivity";

private Button mStartBtn;
   private Handler mHandler;
   private HandlerThread mHandlerThread;

@Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_handler_thread);
       mStartBtn = findViewById(R.id.start_btn);

mHandlerThread = new HandlerThread("THREAD_NAME");
       mHandlerThread.start();
       mHandler = new Handler(mHandlerThread.getLooper());

mStartBtn.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               mHandler.post(new Runnable() {
                   @Override
                   public void run() {
                       Log.d(TAG, Thread.currentThread().getId() + " " + String.valueOf((Looper.myLooper() == Looper.getMainLooper())) + " 任务:" + this.hashCode());
                       SystemClock.sleep(3000);
                   }
               });
           }
       });
   }

@Override
   protected void onDestroy() {
       super.onDestroy();
       mHandlerThread.quit();
   }
}

快速三击按钮,打印日志如下:

Android HandlerThread案例详解

可以发现,三次不同的任务按开始的顺序执行,而且是运行在子线程中,那到底是怎么实现的呢?

源码解析


public class HandlerThread extends Thread {
   int mPriority;
   int mTid = -1;
   Looper mLooper;
   private @Nullable Handler mHandler;

public HandlerThread(String name) {
       super(name);
       mPriority = Process.THREAD_PRIORITY_DEFAULT;
   }

public HandlerThread(String name, int priority) {
       super(name);
       mPriority = priority;
   }

protected void onLooperPrepared() {
   }

@Override
   public void run() {
       // 获取线程 id
       mTid = Process.myTid();
       //构建一个 Looper
       Looper.prepare();
       synchronized (this) {
           mLooper = Looper.myLooper();
           notifyAll();
       }
       //设置线程优先级
       Process.setThreadPriority(mPriority);
       onLooperPrepared();
       Looper.loop();
       // Looper 循环
       mTid = -1;
   }

// 获取当前线程的 Looper,
   public Looper getLooper() {
       if (!isAlive()) {
           return null;
       }

synchronized (this) {
           while (isAlive() && mLooper == null) {
               try {
                   wait();
               } catch (InterruptedException e) {
               }
           }
       }
       return mLooper;
   }

/**
    * @return a shared {@link Handler} associated with this thread
    * @hide 方法隐藏掉,无法调用
    */
   @NonNull
   public Handler getThreadHandler() {
       if (mHandler == null) {
           mHandler = new Handler(getLooper());
       }
       return mHandler;
   }

//线程退出方法,主要是调用 Looper.quit() 方法,不然一直在循环
   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;
   }

public int getThreadId() {
       return mTid;
   }
}

通读下来,如果熟悉 Handler 原理的同学大概就明白 HandlerThread 的机制了:

  • HandlerThread 运行 start() 方法,回调 run() 方法。

  • 在 run() 方法中通过 Looper.prepare() 来创建消息队列,并通过 Looper.looper() 方法来开启消息循环。

  • 由于 Loop.loop() 是一个死循环,导致  run() 也是无线循环,因此当我们不需要使用 HandlerThread 的时候,要调用它的 quit() 方法或者 quiteSafely() 方法。

来源:https://www.jianshu.com/p/9807338a38c3

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com