Android之多线程

为什么要有多线程呢?

        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]来取值。
}
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值