摘要:

  在Android开发中经常会使用到线程,一想到线程,很多同学就立即使用new Thread(){...}.start()这样的方式。这样如果在一个Activity中多次调用上面的代码,那么将创建多个匿名线程,程序运行的越久可能会越来越慢。因此,需要一个Handler来启动一个线程,以及删除一个线程,保证线程不会重复的创建。

正文:

1、创建Handler的一般方式

一般会使用Handler handler = new Handler(){...}创建。
这样创建的handler是在主线程即UI线程下的Handler,即这个Handler是与UI线程下的默认Looper绑定的。
Looper是用于实现消息队列和消息循环机制的。
因此,如果是默认创建Handler那么如果线程是做一些耗时操作如网络获取数据等操作,这样创建Handler是不行的。

2、使用HandlerThread 

HandlerThread实际上就一个Thread,只不过它比普通的Thread多了一个Looper。
我们可以使用下面的例子创建Handler :

HandlerThread thread = new HandlerThread("MyHandlerThread");
thread.start();
mHandler = new Handler(thread.getLooper());
mHandler.post(mBackgroundRunnable);

创建HandlerThread时要把它启动了,即调用start()方法。
然后创建Handler时将HandlerThread中的looper对象传入。
那么这个mHandler对象就是与HandlerThread这个线程绑定了(这时就不再是与UI线程绑定了,这样它处理耗时操作将不会阻塞UI)。
最后把实现耗时操作的线程post到mHandler的消息队列里面。
注意的是,mBackgroundRunnable这个线程并没有启动,因为没有调用start()方法。

完整demo:

public class MainActivity extends Activity implements OnClickListener{
public static final String TAG = "MainActivity";
private Handler mHandler;
private boolean mRunning = false;
private Button mBtn; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); HandlerThread thread = new HandlerThread("MyHandlerThread");
thread.start();//创建一个HandlerThread并启动它
mHandler = new Handler(thread.getLooper());//使用HandlerThread的looper对象创建Handler,如果使用默认的构造方法,很有可能阻塞UI线程
mHandler.post(mBackgroundRunnable);//将线程post到Handler中 mBtn = (Button)findViewById(R.id.button);
mBtn.setOnClickListener(this);
} @Override
protected void onResume() {
super.onResume();
mRunning = true;
} @Override
protected void onStop() {
super.onStop();
mRunning = false;
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
} //实现耗时操作的线程
Runnable mBackgroundRunnable = new Runnable() { @Override
public void run() {
//----------模拟耗时的操作,开始---------------
while(mRunning){
Log.i(TAG, "thread running!");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//----------模拟耗时的操作,结束---------------
}
}; @Override
protected void onDestroy() {
super.onDestroy();
//销毁线程
mHandler.removeCallbacks(mBackgroundRunnable);
} @Override
public void onClick(View v) {
Toast.makeText(getApplication(), "click the button!!!", Toast.LENGTH_SHORT).show();
}
}

如果在onCreate()方法中里面没有使用HandlerThread而是在直接使用Handler的默认构造方法来创建Handler,那么mBackgroundRunnable将会阻塞UI线程。

 3、线程销毁 

用上面的方式来创建线程,在销毁时就可以使用

mHandler.removeCallbacks(mBackgroundRunnable); 

销毁一个线程,这样就可以避免在多次进入同一个Activity时创建多个同时运行着的线程。

原文:

Android线程的创建与销毁[2014-07-11](2013-06-19).http://www.bdqn.cn/news/201306/9538.shtml

Android线程的创建与销毁的更多相关文章

  1. 从微信推送看Android Service的创建和销毁

    启动服务是有两组参数影响服务的状态. 1.在onStartCommand(Intent intent, int flags, int startId) 接口中返回值,例如 START_STICKY;  ...

  2. APUE学习之多线程编程(一):线程的创建和销毁

    一.线程标识      和每个进程都有一个进程ID一样,每个线程也有一个线程ID,线程ID是以pthread_t数据类型来表示的,在Linux中,用无符号长整型表示pthread_t,Solaris ...

  3. 理解Android线程创建流程

    copy from : http://gityuan.com/2016/09/24/android-thread/ 基于Android 6.0源码剖析,分析Android线程的创建过程 /androi ...

  4. Android(java)学习笔记267:Android线程池形态

    1. 线程池简介  多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.     假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...

  5. android线程与线程池-----线程池(二)《android开发艺术与探索》

    android 中的线程池 线程池的优点: 1 重用线程池中的线程,避免了线程的创建和销毁带来的性能开销 2 能有效的控制最大并发数,避免大量线程之间因为喜欢抢资源而导致阻塞 3 能够对线程进行简单的 ...

  6. android 线程那点事

    在操作系统中,线程是操作系统调度的最小单元,同时线程又是一种受限的系统资源,即线程不可能无限制的产生,并且线程的创建和销毁都会有相应的开销,当系统中存在大量的线程时,系统会通过时间片轮转的方式调度每个 ...

  7. Android(java)学习笔记211:Android线程池形态

    1. 线程池简介  多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.     假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...

  8. android线程及线程池

    众所周知,在UI系统中进行一些耗时操作,都会导致卡顿现象,因为一次刷新在16ms,如果当次操作过了这个时间,那么用户就能感觉到明显的卡顿,甚至引起ANR . 对于这种情况,一般都是再起一个线程,进行一 ...

  9. java/android线程池详解

    一,简述线程池: 线程池是如何工作的:一系列任务出现后,根据自己的线程池安排任务进行. 如图: 线程池的好处: 重用线程池中的线程,避免因为线程的创建和销毁所带来的性能开销. 能有效控制线程池的最大并 ...

随机推荐

  1. C++中四种类型转换方式(ynamic_cast,const_cast,static_cast,reinterpret_cast)

    Q:什么是C风格转换?什么是static_cast, dynamic_cast 以及 reinterpret_cast?区别是什么?为什么要注意? A:转换的含义是通过改变一个变量的类型为别的类型从而 ...

  2. 【Spring】SpringMVC之拦截器

    Spring的HandlerMapping处理器支持拦截器应用.当需要为某些请求提供特殊功能时,例如实现对用户进行身份认证.登录检查等功能. 拦截器必须实现HandlerInterceptor接口,实 ...

  3. SqlLocalDB2014使用笔记

    标签: 软件开发,数据库肯定是必不可少的当然是数据库了,在.Net开发中兼容性最好的莫过于微软的亲儿子“SqlServer”了,但是在安装SqlServer的安装随便找个版本就是一个多G或者几百兆,安 ...

  4. lineman 的理念与 modern web app

    无意中翻到javascript 有个 lineman工具, 提供了一些脚手架 以及 默认的app目录结构,同时还附带了诸多前端的性能优化工具,在他的主页还发现其理念与我之前关于web app的开发模型 ...

  5. MFC中无标题栏窗口的移动

    原文链接: http://blog.sina.com.cn/s/blog_6288219501015dwa.html   移动标准窗口是通过用鼠标单击窗口标题条来实现的,但对于没有标题条的窗口,就需要 ...

  6. js中为什么你不敢用 “==”

    文章引用:http://0313.name/archives/480 前言 类型转换在各个语言中都存在,而在 JavaScript 中由于缺乏对其的了解而不慎在使用中经常造成bug被人诟病.为了避免某 ...

  7. [转]在windows上实现多个java jdk的共存解决办法

    问题背景 公司项目中应用到的jdk环境为1.6,最近在家学习IntelliJ IDEA中sdk多环境配置时,想安装Jdk1.8,作为学习基础.那么问题来了,公司项目扩展不支持jdk1.8,为了既能满足 ...

  8. [转]byte为什么要与上0xFF?

    无意间翻看之间的代码,发现了一段难以理解的代码. byte[] bs = digest.digest(origin.getBytes(Charset.forName(charsetName))) ; ...

  9. JAXB--@XmlType注解标注xml生成顺序

    默认情况下,Jaxb编组出来的xml中的字段顺序是随机的,你可以使用@XmlType的propOrder属性 来指定序列化的顺序.   第一步:定义java类时,使用@XmlType(propOrde ...

  10. HDU 1019 Least Common Multiple 数学题解

    求一组数据的最小公倍数. 先求公约数在求公倍数.利用公倍数,连续求全部数的公倍数就能够了. #include <stdio.h> int GCD(int a, int b) { retur ...