文档章节

Handler and HandlerThread Tips

daveztong
 daveztong
发布于 2014/11/06 21:25
字数 1063
阅读 71
收藏 2
Handler在Android的开发中算是最常用的东东,但有很多小小的tips或许很多人都不知道。关于Handler,Looper,MessageQueue网上已有很多文章了,这里就不在赘述。 1.从其他线程获取一个与UI线程关联的Handler:
Handler handler = new Handler(Looper.getMainLooper());
2.任务调度应该都知道可以使用post(),如果想使得你post出的runnable最快的执行,可以这样干:
handler.postAtFrontOfQueue(new Runnable(){
  public void run() {
    // do some work on the main thread.
  }
});
3.Handler是如此的常见,所以在后台线程中如果想更新UI都可以不使用handler,因为他已经整合到view中了,直接使用view.post()即可更新UI:
final TextView text = (TextView) findViewById(R.id.text);
  Thread thread = new Thread(){
  public void run(){
    // long time work
    text.post(new Runnable(){
      public void run() {
      text.setText("xxxx"); 
      }
    });
  }
};
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
4.如果你为耗时工作开了一个后台线程,最好是将线程的优先级设置为最低以防止主线程出现饥饿状态(CPU未分配足够的时间)。
thread.setPriority(Thread.MIN_PRIORITY);
5.可以通过删除已post的runnable来 取消待执行的runnable:
final Runnable runnable = new Runnable(){
  public void run() {
  // … do some work
  }
};
handler.postDelayed(runnable, TimeUnit.SECONDS.toMillis(10));
  Button cancel = (Button) findViewById(R.id.cancel);
  cancel.setOnClickListener(new OnClickListener(){
    public void onClick(View v) {
    handler.removeCallbacks(runnable);
  }
});
通过这种方式只能取消未执行的runnable,如果正在执行那就不会去取消了。 6.使用Message传递消息时,出于效率问题,最好使用Message.obtain(...)方法,如果每次都去用构造器new一个,如果频率较高,那就等于无形中给GC增加了很多工作:
handler.sendMessage(Message.obtain(handler, what, obj));
7.,send消息有与post类似的方法,如发送消息到队列的头部:
handler.sendMessageAtFrontOfQueue(msg);
8.取消已发送的消息。与取消runnable类似,我们也可以取消已发送但未执行的消息,而且取消message比取消post出的runnable更方便,想要取消runnable的话得需要一个runnable的引用,取消message只需要知道message的what值就行了:
handler.removeMessages(what);
9.HandlerThread的使用。Handler可以绑定到任何我们创建的线程上,这样一个线程就可以把工作交给另外一个线程来做,如可以将UI线程的工作交给后台线程,后台线程再将工作给其他线程来做。我们自己设置一个Looper thread和handler,但更方便的是使用系统提供的HandlerThread。
HandlerThread thread =new HandlerThread("tag", Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// HandlerThread包装了Looper
Handler handler = new Handler(thread.getLooper());
// 使用runnable
handler.post(new Runnable(){
  public void run() {
    // ... do some work in the background thread
  }
});
// 发送message
Handler.Callback callback = new Handler.Callback(){ … };
Handler handler = new Handler(thread.getLooper(), callback);
为了防止内存的意外泄露,尽量将HandlerThread的生命周期和Activity的生命周期捆绑在一起。HandlerThread可以通过调用quit()来使其停止。 10.Handler使用过程中容易出现的问题。
  • 隐式引用的泄露。场景如下:
final Runnable runnable = new Runnable(){
  public void run() {
    // … do some work
  }
};
handler.postDelayed(runnable, TimeUnit.SECONDS.toMillis(10))
Java中匿名内部类对外部类实例有着一个隐式的引用。上面例子post了一个延迟10秒执行的任务,如果在任务执行之前activity就已经finish了,那么这个activity实例是不能被回收的,因为还存在对他的引用。通常的解决办法就是讲runnable或handler定义成top-level或者static的类,这样就很容易的将其置为空,方便垃圾回收。此外,当activity要finish的时候,如果创建了HandlerThread,要保证对其进行quit(),避免继续执行,且让GC能对其尽快的回收。
  • 显式引用的泄露。在做界面交互时,可能会用到view的引用,并将其传给runnable或handler,如下:
static class MyRunnable implements Runnable {
  private View view;
  public MyRunnable(View view) {
    this.view = view;
  }
  public void run() {
    // … do something with the view. 
  }
}
这里保存对view的强引用,如果runnable的存活时间大于view,那么又造成了资源的泄露,一个解决办法就是使用WeakReference,使用的时候对view的引用进行null检查:
static class MyRunnable implements Runnable {
  private WeakReference<View> view;
  public MyRunnable(View view) {
    this.view = new WeakReference<View>(view);
  }
  public void run() {
    View v = view.get(); // might return null
    if (v != null) {
      // … do something with the view.
    }
  }
}
当view不存在任何强引用时,WeakReference也将失去对其的引用。

© 著作权归作者所有

daveztong
粉丝 4
博文 93
码字总数 21482
作品 0
成都
程序员
私信 提问
多线程并发——HandlerThread

HandlerThread本质上就是一个普通Thread,只是这个线程内部有一个looper,而这个looper有一个消息队列MessageQue,它通过不断的用looper去检查MessageQue然后取出消息然后处理。 基本用法 创...

蜗牛崛起
2018/01/23
70
0
Android HandlerThread详解

转载请注明出处:http://blog.csdn.net/vnanyesheshou/article/details/75073307 对于Handler不太懂的可以参考我的这两篇文章: Android Handler的基本使用 深入理解Handler、Looper、Messa...

VNanyesheshou
2017/07/14
0
0
Android线程的创建与销毁

在Android开发中经常会使用到线程,一想到线程,很多同学就立即使用new Thread(){...}.start()这样的方式。这样如果在一个Activity中多次调用上面的代码,那么将创建多个匿名线程,程序运行的...

带梦想一7飞
2014/03/06
98
0
Android面试必会知识点 - ANR详解

最近在公司出差过多,感觉自己快被废了,这时候正好有大公司给了面试机会,于是就去试试,虽然最后Tencent没有要我,但是过程中让我对Android有了更新的认知,把我的对于Android的理解又提升...

吴雨声
2018/07/02
0
0
笔记38 | Android线程之Looper.prepare()+Looper.loop()和HandlerThread()浅析

合抱之木,生於毫末;九層之台,起於累土;千里之行,始於足下。《老子》 地址 http://www.jianshu.com/p/dc2a4fb0fcde 目录 Looper概念 Looper实例 HandlerThread概念 HandlerThread实例 Lo...

项勇
2017/11/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

前端面试题汇总

一. HTML常见的兼容性 1.HTML5 标签在低版本浏览器不兼容 解决办法:使用html5shiv库,引入下列语句 <!--[if lte IE 8]> <script src="https://cdn.bootcss.com/html5shiv/r29/html5.js"></sc......

蓝小驴
38分钟前
10
0
OSChina 周四乱弹 —— 我气的脸都黑了!

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 小小编辑推荐《Red Battle》- 高橋李依 / 豊崎愛生 《Red Battle》- 高橋李依 / 豊崎愛生 手机党少年们想听歌,请使劲儿戳(这里) @丶Lion ...

小小编辑
51分钟前
668
23
找OSG教程, B站就有

https://www.bilibili.com/video/av64849038?from=search&seid=11632913960900279653

洛克人杰洛
今天
6
0
学习记录(day07-Vue组件、自定义属性、自定义事件)

[TOC] 1.1.1什么是组件 一个vue文件就是一个组件 组件将html标签/css样式/对应JS打包成一个整体,也可以理解钻进一个具有样式和特效的自定义标签。 一、编写组件(提供方)<template> <di...

庭前云落
今天
5
0
使用Prometheus监控SpringBoot应用

通过之前的文章我们使用Prometheus监控了应用服务器node_exporter,数据库mysqld_exporter,今天我们来监控一下你的应用。(本文以SpringBoot 2.1.9.RELEASE 作为监控目标) 编码 添加依赖 使...

JAVA日知录
今天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部