转自http://blog.sina.com.cn/s/blog_bd338b2101017nvv.html
在Android应用程序中,为了避免ANR(Application Not Response)异常,需要把耗时任务放置在子线程中来完成。或者使用AsyncTask类来完成。
一、多线程和线程池:
1. 实现方式:
1) 继承自Thread类,重写它run()方法。通过它的start()来启动线程。
2) 定义一个实现Runnable接口的类(重写它的run()方法),以这个对象来构造Thread对象。
2. java.util.Timer类的应用。
3. 线程池:使用ExecutorService类的实例来表示,使用Executors类提供的静态方法来创建。
1) Single Thread Executor: 只有一个线程的线程池,因此所有提交的任务是顺序执行。
代码:ExecutorService Executors.newSingleThreadExecutor();
2) Cached Thread Pool: 线程池里有很多线程需要同时执行,老的可用线程将被新的任务触发重新执行。超过60秒内没执行的线程将被终止并从池中删除,代码:Executors.newCachedThreadPool()
★3) Fixed Thread Pool: 拥有固定线程数的线程池,如果没有任务执行,那么线程会一直等待。
代码:ExecutorService Executors.newFixedThreadPool(int nThreads)
4) Scheduled Thread Pool: 用来调度即将执行的任务的线程池,代码:Executors.newScheduledThreadPool()
5) Single Thread Scheduled Pool: 只有一个线程,用来调度执行将来的任务,代码:Executors.newSingleThreadScheduledExecutor()
6) 自定义一个线程池:
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(6, 30, 30L, TimeUnit.SECONDS, new LinkedBlockingQueue());
threadPool.execute(new Runnable() {…});
7) 线程池不使用时,需要调用它的shutdown()方法进行关闭。
★★二、Handler机制:Android程序中,子线程中需要更改主线程(UI线程)中的UI组件的属性值时,就需要使用Handler来处理。
1. Android UI操作不是线程安全的,所以在Activity中新启动的线程不能访问本Activity中的UI组件。
要让线程动态改变UI组件的属性值,必须借助于Handler。
2. Handler的使用:在新启动的线程中发送消息。在主线程(UI线程)中获取消息并处理。
3. Handler使用步骤:
1) 在主线程中创建Handler子类对象,并重写处理消息的方法(handlerMessage())。
2) 在新启动的线程(子线程)中创建消息并发送。
4. Message消息对象的常用属性:
1) int what: 标识消息的一个识别码(整数值)
2) Object obj: 用于传递数据的一个Object属性。
5. Handler类的常用方法:
1) 构造方法:
Handler()
Handler(Handler.Callback callback); //传入用于处理消息的回调接口
2) 处理消息(用于被重写)
public void handleMessage (Message msg);
3) 发送消息
public final boolean sendEmptyMessage(int what)
public final boolean sendMessage(Message msg)
public boolean sendMessageAtTime(Message msg, long millis)
public final boolean sendMessageDelayed(Message msg, long millis)
4) 从消息池中取出一个消息
public final Message obtainMessage()
public final Message obtainMessage(int what)
public final Message obtainMessage(int what, Object obj)
三、android.os.AsyncTask 异步任务:封装好了多线程及Handler机制
1. 构造时的三个模板参数:
Params:传递给后台任务的参数类型。(如:远程图片的URL地址)
Progress:后台计算执行过程中,进度单位(progress units)的类型。
Result:后台执行返回的结果的类型。
2. 五个回调方法:
1) onPreExecute():准备运行后台任务时。一般做一些初始化工作(如:显示进度对话框)。 注意,这个方法在UI线程(主线程)中执行
2) doInBackground(Params...):正在后台运行。在后台线程中执行。一般编写需要在后台线程中执行的代码。注意,这个在后台线程中执行
3) onProgressUpdate(Progress...):进度更新时。一般就是更新进度显示。注意,这个方法在UI线程(主线程)中执行。一般在doInBackground()方法中调用publishProgress()方法来触发。
4) onPostExecute(Result):后台任务完成后。一般做一些清理资源工作(如:隐藏进度对话框)。 注意,这个方法在UI线程(主线程)中执行
5) onCancelled():取消任务时。一般做一些清理资源工作
3. 执行异步任务的方法:
MyAsyncTask task = new MyAsyncTask();
task.execute(Params...);
4. 取消异步任务的方法:
task.cancel(true);
5. AsyncTask的实例必须在UI线程(主线程)中创建?
execute()方法必须在UI线程(主线程)中调用
该AsyncTask只能被执行一次,多次调用时将会出现异常