为什么要有多线程呢?
1、为了提供良好的用户体验,我们必须保证程序有高响应性,所以不能够在UI线程中进行耗时的计算或I/O操作。
2、Android操作系统在下面情况下会强制关闭程序。
UI线程在5秒内没有响应;
广播对象不能在10秒内完成onReceive方法。
因此需要采用多线程的方法,将大规模的计算放在后台线程中计算,然后将计算结果显示到前台。
Thread mThread =newThread()
{
@Override
public voidrun()
{
timeConsumingProcess();
}
};
mThread.start()
新建用户线程:
由于Android操作系统的线程安全机制,不能在非UI线程中重绘UI,所以在用户线程中进行类似更改进度条,修改TextView文字等操作都会造成程序强制关闭(FC) Android提供了两种方法解决上述问题:
A、Handler
B、Asynctask
Handler:Android操作系统在UI线程中,缺省维护该MessageQueue和一个Looper。
Looper伪码
while(true)
{
Msg=getFirstMessage(MessageQueue)
if(Msg!=null)
processMessage()
}
Looper通过一个死循环,当有消息Message加入队列时,通过FIFO的顺序处理消息。一个Message中包括了处理Message的Handler对象还有消息内容。这种机制对应这设计模式中的命令模式。Handler与UI线程是同一个线程,所以我们在用户线程中完成计算之后,可以通过向消息队列加入一个消息,通知特定的Handler去更改UI。
Asynctask:内部实现一个线程池,每个后台任务会提交到线程池中的线程执行,然后使用Thread+handler的方式回调函数(对程序员透明)。AsyncTask抽象出后台线程运行的五个状态,分别是:1、准备运行,2、正在后台运行,3、进度更新,4、完成后台任务,5、取消任务,对于这五个阶段,AsyncTask提供了五个回调函数。
准备运行:onPreExecute()
该回调函数在任务被执行之后立即由UI线程调用。这个步骤通常用来建立任务,在用户接口(UI)上显示进度条。
正在后台运行:doInBackground(Params...)
该回调函数由后台线程在onPreExecute()方法执行结束后立即调用。通常在这里执行耗时的后台计算。计算的结果必须由该函数返回,并被传递到
onPostExecute()中。在该函数内也可以使用publishProgress(Progress...)来发布一个或多个进度单位(unitsofprogress)。这些值将会在
onProgressUpdate(Progress...)中被发布到UI线程。
进度更新:onProgressUpdate(Progress...)
该函数由UI线程在publishProgress(Progress...)方法调用完后被调用。一般用于动态地显示一个进度条。
完成后台任务:onPostExecute(Result) 当后台计算结束后调用。后台计算的结果会被作为参数传递给这一函数。
取消任务:onCancelled () 在调用AsyncTask的cancel()方法时调用。
AsyncTask中有三个参数,如class MyTask extends AsyncTask<参数1,参数2,参数3>{}
a)参数1:向后台任务执行过程方法传递参数的类型
b)参数2:在后台任务执行过程中,要求主UI线程处理中间状态,通常是一些UI处理中传递的参数类型,后台计算执行过程中,进度单位
(progress units)的类型。(就是后台程序已经执行了百分之几了。)
c)参数3:后台任务执行完返回时的参数类型
AsyncTask并不总是需要使用上面的全部3种类型。标识不使用的类型很简单,只需要使用Void类型即可。
ServiceApplication.java
class MyTask extends AsyncTask<Integer,Integer,Integer>
{
@Override
protected Integer doInBackground(Integer... params) {
//重写该函数,实现后台处理大规模计算
return null;}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
//重写该回调函数,更新UI
}
}
很清晰的一套模板方法设计模式,只需要重写关键事件,不用去了解底层的多线程
并发的实现机制。
private class myAsync extends
AsyncTask<Void, Integer, Void>
{ int duration =0;
int current =0;
@Override
//在doInBackground里执行耗时操作,在适当的时候调
用publishProgress(n)来设置进度条进度。
protected Void doInBackground(Void...
params){
do{ current+=10;
try{ publishProgress(current);
//参数类型是AsyncTask<Void, Integer, Void>中的
Integer决定的,onProgressUpdate中可以得到这个值去
更新UI主线程,这里是异步线程
Thread.sleep(1000);
if(mProgressBar.getProgress() >=100){
break; }
}catch(Exception e) { }
}while
(mProgressBar.getProgress() <=100);
return null;
}
@Override
protected void onProgressUpdate(Integer...
values){super.onProgressUpdate(values);
mProgressBar.setProgress(values[0]);
//注意:这个函数在doInBackground调用
publishProgress时触发,虽然调用时只有一个参数, 但是
这里取到的是一个数组, 所以要用progesss[0]来取值, 第n
个参数就用progress[n]来取值。
}
}