Handler机制和AsyncTask

一、Handler机制

Handler是什么

为什么要用Handler
Android在设计开发的时候,就封装了一套消息创建、传递、处理机制,如果不遵循这样的机制来更新UI,就会抛出异常信息
Handler、Looper、messagequeue的关系

在应用创建时,存在一个ActivityThread线程,在这个线程中会调用PrepareMainLooper,然后调用prepare方法来创建Looper,内部创建出一个MesageQueue

Handler内部机制
首先handler会去获取主线程中的looper对象,并且拿到主线程中的MesageQueue,这样Handler looper mesageQueue就对应成了1:1:1的关系,并产生了关联,handler就能够从MesageQueue中获取到消息,并进行处理了

Handler.sendEmptyMessage方法解析
其实,内部是首先获取到了一个消息队列的对象,判断一下消息队列是否为null,如果不为null的话,那就把这个消息放在消息队列中,通过Looper.loop让消息队列轮询起来

loop方法里面有一个for的死循环,不断地从消息队列里边获取消息,如果没有消息的话,那么就会在这里阻塞,直到获取到下一个消息

获取到一个消息以后会进行判断,如果这个消息为空,就会return,否则就会调用message.dispatchMessage()方法进行对消息的处理

总结:
就相当于我们使用百度云盘,我们就相当于Handler,百度云盘相当于MessageQueue,百度云盘后台的逻辑就相当于looper,我们平时看到一些认为对自己有用的资料或者比较感兴趣的电影的时候,我们会把这些东西存在百度云盘中,这个过程相当于Handler调用sendMessage的过程,而百度云盘会把这些东西按照一定的顺序存起来,当我们什么时候需要用这些东西的时候,就回去点击下载,这个过程就相当于handleMessage的过程,从这个队列中获取我们所需要的

Handler遇到的问题:
loop方法里面又一个死循环,为什么不会出现,ANR异常,
答:应用之所以打开的时候没有退出,正是因为这个死循环没有结束,如果没有这个死循环,则直接就会抛出异常,平时开发中我们之所以遇到ANR异常,是因为我们在主线程中进行了耗时操作,阻塞了这个死循环的执行

在子线程中创建Handler对象,需要注意什么
我们需要手动调用一下Looper.loop 和Looper.prepare方法,之所以我们在主线程中不需要手动调用是因为系统已经帮我们自动调用了,而如果我们在子线程中调用的话,那么需要我们手动调用这两个方法。

非UI线程真的不可以更新UI吗?
正常情况下

更新UI时,内部会调用invitate()方法,然后检查当前线程是否是在主线程中,

二、AsyncTask

Android UI是线程不安全的,如果想要在子线程里进行UI操作,就需要借助android的异步消息处理机制,为了更加方便我们在子线程中更新UI元素,Android从1.5版本就引入了一个AsyncTask类,使用它就可以非常灵活方便地从子线程切换到UI线程
AsyncTask的基本用法
由于AsyncTask是一个抽象类,所以如果我们想使用它,就必须要创建一个子类去继承它,在继承时我们可以为AsyncTask类指定三个泛型参数,这三个参数的用途如下:
1. Params
在执行AsyncTask时需要传入的参数,可用于在后台任务中使用。
2. Progress
后台任务执行时,如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位。
3. Result
当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型。

  1. class DownloadTask extends AsyncTask

猜你喜欢

转载自blog.csdn.net/qq_32890771/article/details/76652169