在Android开发中有时候需要进行一些耗时的操作,如网络请求或者IO操作,如果你使用的是Android4.0以后,那你会发现,只要是写在UI线程中的HTTP请求,运行时都会报错,这是因为Android在4.0以后为了防止应用的ANR(aplication Not Response)异常
在Android API>9 (Honeycomb及之后)版本里,对UI线程/主线程里是不允许联网操作的,如果有网络操作,会抛出NetworkOnMainThreadException的异常。
为了避免ANR(Application Not Response)异常,可以把网络请求或IO操作用多线程来完成,或者使用AsyncTask。
多线程
一.创建线程
1.Thread类
继承Thread类,Override 其 run(){}方法,然后调用start()方法即可启动子线程。 new Thread() {
@Override
public void run(){
super.run();
//do something
}
}.start();
2.Runnable接口
实现Runnable接口中的run(){}方法,但是注意,Runnable并不提供start()方法,因此需要使用Thread的public Thread(Runnable targer)构造方法来实现开线程。
class MyRunnable implements Runnable{
@Override
public void run(){
//do something
}
}
MyRunnable mt = new MyRunnable();
new Thread(a).start();
注意:Runnable相比于直接继承Thread的优势:
(1)java只支持单继承的方式,继承Thread不够灵活,而一个类可以实现多个接口。
(2)实现Runnable接口,可以让同一个类开多条线程,使用synchronized方法修饰run()方法,即可实现多线程之间的资源共享。
class MyRunnable implements Runnable{
@Override
public synchronized void run(){
//do something
} }
MyRunnable a = new MyRunnable();
MyRunnable b = new MyRunnable();
new Thread(a).start();
new Thread(b).start();
3.使用Timer调度TimerTask
使用Timer不仅可以定时执行任务,也可以配合TimerTask执行多线程操作。
class myTimeTask extends TimerTask{
@Override
public void run() {
//do something
//System.gc();
}
}
Timer timer = new Timer();
timer.schedule(new myTimeTask(),1000);//1秒后执行任务
注意:
(1)如果使用同一个Timer()来调度,前一个TimerTask执行完后才会执行下一个,需要同时开多线程的时候,应使用多个Timer()来分别调度。
(2)程序的Timer线程在运行时,这个程序就会保持运行,需要终止Timer线程时可以调用Timer的cancle()方法。
(3)Timer中的TimerTask执行完后,整个程序并不会退出,需要等待垃圾回收时程序才会退出,所以可以在run方法最后加上System.gc();
4.ThreadPoolExecutor线程池
二.使用Handler
安卓中不允许在子线程中操作UI,因为UI主线程并不线程安全,所以要在子线程中操作UI,需要使用Handler机制。
创建子类继承Handler,并Override其handleMessage(Message msg)方法,即可根据Message对象的值在函数体中操作UI。
同时,在子线程中新建Message,并通过sendMessage()来传递消息。
Message可以携带的数据有
arg1: int 存放整型数据
arg2: int 存放整型数据
obj: Object 存放Object类型的任意对象
replyTo: Messenger 用来指定此Message发送到何处的可选Messager对象
what: int 用户自定义消息代码
例如:
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg){
super.handleMessage(msg);
//do something
}
};
new Thread() {
@Override
public void run() {
super.run();
Message msg = new Message();
msg.obj = Object;
mHandler.sendMessage(msg);
}
}.start();
异步任务 AsyncTask