欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android HandlerThread的使用及原理详解

程序员文章站 2024-01-21 09:12:46
一、handlerthread的含义 handlerthread能够新建拥有looper的线程。这个looper能够用来新建其他的handler。(线程中的loope...

一、handlerthread的含义

handlerthread能够新建拥有looper的线程。这个looper能够用来新建其他的handler。(线程中的looper)需要注意的是,新建的时候需要被回调。

二、handlerthread的用法

一般情况下,我们会经常用handler在子线程中更新ui线程,那是因为在主线程中有looper循环,而handlerthread新建拥有looper的子线程又有什么用呢?

必然是执行耗时操作。举个例子,数据实时更新,我们每10秒需要切换一下显示的数据,如果我们将这种长时间的反复调用操作放到ui线程中,虽说可以执行,但是这样的操作多了之后,很容易会让ui线程卡顿甚至崩溃。

于是,就必须在子线程中调用这些了。
handlerthread继承自thread,一般适应的场景,便是集thread和handler之所长,适用于会长时间在后台运行,并且间隔时间内(或适当情况下)会调用的情况,比如上面所说的实时更新。

三、实现每2秒更新一下ui

public class mainactivity extends appcompatactivity {
 
  private textview tvmain;
 
  private handlerthread mhandlerthread;
  //子线程中的handler
  private handler mthreadhandler;
  //ui线程中的handler
  private handler mmainhandler = new handler();
 
  //以防退出界面后handler还在执行
  private boolean isupdateinfo;
  //用以表示该handler的常熟
  private static final int msg_update_info = 0x110;
 
  @override
  protected void oncreate(bundle savedinstancestate)
  {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_main);
 
    tvmain = (textview) findviewbyid(r.id.tv_main);
 
    initthread();
  }
 
 
  private void initthread()
  {
    mhandlerthread = new handlerthread("check-message-coming");
    mhandlerthread.start();
 
    mthreadhandler = new handler(mhandlerthread.getlooper())
    {
      @override
      public void handlemessage(message msg)
      {
        update();//模拟数据更新
 
        if (isupdateinfo)
          mthreadhandler.sendemptymessage(msg_update_info);
      }
    };
 
  }
 
  private void update()
  {
    try
    {
      //模拟耗时
      thread.sleep(2000);
      mmainhandler.post(new runnable()
      {
        @override
        public void run()
        {
          string result = "每隔2秒更新一下数据:";
          result += math.random();
          tvmain.settext(result);
        }
      });
 
    } catch (interruptedexception e)
    {
      e.printstacktrace();
    }
 
  }
 
  @override
  protected void onresume()
  {
    super.onresume();
    //开始查询
    isupdateinfo = true;
    mthreadhandler.sendemptymessage(msg_update_info);
  }
 
  @override
  protected void onpause()
  {
    super.onpause();
    //停止查询
    //以防退出界面后handler还在执行
    isupdateinfo = false;
    mthreadhandler.removemessages(msg_update_info);
  }
 
  @override
  protected void ondestroy()
  {
    super.ondestroy();
    //释放资源
    mhandlerthread.quit();
  }
}

四、handlerthread 原理

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;
  }
 
 
  protected void onlooperprepared() {
  }
 
  @override
  public void run() {
    mtid = process.mytid();
    looper.prepare();
    synchronized (this) {
      mlooper = looper.mylooper();
      notifyall();
    }
    process.setthreadpriority(mpriority);
    onlooperprepared();
    looper.loop();
    mtid = -1;
  }
 
 
  public looper getlooper() {
    if (!isalive()) {
      return null;
    }
 
    // if the thread has been started, wait until the looper has been created.
    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;
  }
 
 
  public int getthreadid() {
    return mtid;
  }
}

首先我们可以看到handlerthread继承自thread,因此在run()中的逻辑都是在子线程中运行的。

接下来就是两个关键的方法,run()和getlooper():
run()中可以看到是很简单的创建looper以及让looper工作的逻辑。
run()里面当mlooper创建完成后有个notifyall(),getlooper()中有个wait(),这有什么用呢?因为的mlooper在一个线程中执行创建,而我们的handler是在ui线程中调用getlooper()初始化的。
也就是说,我们必须等到mlooper创建完成,才能正确的返回。getlooper();wait(),notify()就是为了解决这两个线程的同步问题。