Android中通常分为主线程(UI Thread/ Main Thread)和工作线程(worker Thread).
所有的组件默认都是在主线程里面的,当进行一些耗时的操作时,比如:访问网络或者对数据库进行处理的时候UI Thread 就会被阻塞,如果阻塞时间超过5秒,这是就会出现比较常见的ANR(Application Not Responding)现象,就是弹出一个框框来,等待还是确定退出。虽说,对于android开发来说,出现ANR现象是绝对不允许的,但是我手机上的QQ啊微信啊,还是经常会出现各种ANR,手机配置网络啊等因素,操作不当也会 呵呵。
由于Android UI控件是线程不安全的,所以不能再UI Thread 之外的线程当中对我们的UI控件进行操作 有两条必须要准守的原则:
1、绝对不能在UI Thread当中进行耗时的操作,不能阻塞我们的UI Thread
2、不能再UI Thread之外的线程当中操作我们的UI元素
对此Android提出了两种解决方式
1、Handler机制
2、AsyncTask机制
一、AsyncTask的使用
3个泛型
MyAsyncTask extends AsyncTask<Params,Progress,Result>
Params:传递给异步任务的参数类型
Progress:异步任务在执行的时候的进度 返回给UI线程的参数的类型
Result:异步任务执行完后返回给UI线程的结果的类型
比如下面的例子中下载一张网络图片:
MyAsyncTask extends AsyncTask<String, Integer, byte[]>
String:URL路径
Integer:进度条的单位
byte[]:下载好的图片 以字节数组返回
4个步骤
继承AsyncTask 必须得实现方法 doInBackground(Patams... params)
不过在项目中专业一点,就按四部走吧
onPreExcute();//异步执行前的时候执行,这方法是在UI thread里面执行的 通常可以弹出 显示刷新进度条
doInBackground(Patams... params);//处理异步任务的方法 系统会开辟一个worker Thread执行这个方法 执行完后 将结果发送给 onPostExcute(Result... result);在执行的过程中可以调用publicProgress(Progress...)来跟新任务的进度
onProgressUpdate(progress... values);//在执行异步任务的时候,需要跟新进度到UI界面 也是在UI Thread里面执行的。最长见的就是 进度条的跟新
onPostExcute(Result... result);//异步任务执行完后执行,也是在UI Thread 里面执行的。
其他
1、我们可以在任何时刻来取消我们的异步任务的执行,通过调用 cancel(boolean)方法,调用完这个方法后系统会随后调用 isCancelled() 方法并且返回true。如果调用了这个方法,那么在 doInBackgroud() 方法执行完之后,就不会调用 onPostExecute() 方法了,取而代之的是调用 onCancelled() 方法。为了确保Task已经被取消了,我们需要经常调用 isCancelled() 方法来判断,如果有必要的话。
2、在使用AsyncTask做异步任务的时候必须要遵循的原则:
- AsyncTask类必须在UI Thread当中加载,在Android Jelly_Bean版本后这些都是自动完成的
- AsyncTask的对象必须在UI Thread当中实例化
- excute方法必须在UI Thread当中调用
- 不要手动的去调用AsyncTask的onPreExecute, doInBackground, publishProgress, onProgressUpdate, onPostExecute方法,这些都是由Android系统自动调用的
- AsyncTask任务只能被执行一次
具体的有同学想结合简单的例子来看的,请看这篇文章:
http://www.cnblogs.com/xiaoluo501395377/p/3430542.html
2、AsyncTask的优缺点
优点:
1、简单、快捷
2、过程可控
缺点:
在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来.
随便说下Handler的优缺点(new一个Thread在run方法里面handler.sendEmptyMessage(0);在Handler的实现类里面跟新UI)
在Handler 异步实现时,涉及到Handler, Looper, Message,Thread四个对象,实现异步的流程是主线程启动Thread(子线程)àthread(子线程)运行并生成Message-àLooper获取Message并传递给HandleràHandler逐个获取Looper中的Message,并进行UI变更。
使用的优点(Thread+Runnable+handler):
1.结构清晰,功能定义明确
2. 对于多个后台任务时,简单,清晰
使用的缺点:1.在单个后台异步处理时,显得代码过多,结构过于复杂(相对性)
AsyncTask真正的缺点在于,AsyncTask的全局线程池只有5个,最多5个同时运行,其他的被阻塞(自己new出来的Thread不受影响)
所以AsyncTask不要用于多线程获取网络数据,因为很有可能会产生阻塞,效率降低。
回答一个面试题:
能否同时并发100+asynctask呢?
AsyncTask用的是线程池机制,容量是128,最多同时运行5个core线程,剩下的排队。