Android 的 Handler.post,究竟会发生什么?
Android 的 Handler.post,究竟会发生什么?
最近几天,我一直在尝试弄清楚如果执行以下代码会发生什么:
void function(){ //一些预执行代码 new Handler().post(new Runnable(){ @Override public void run(){ //一些代码 } }); }
似乎它不会阻塞用户界面,所以调用function()的按钮不会在点击后停留在点击位置,直到someCode执行完毕。
但是如果somePreExecutionCode启动一个进度条,进度条会在someCode执行完毕时立即显示。
我知道有AsyncTasks可以用,但还有其他可能性吗?
还有,`new Handler().post`和`View.post`有什么区别?
当创建一个Android应用程序时,系统会创建一个主执行线程。这个线程被称为UI线程,所有与UI相关的操作都在这个线程上进行,以避免同步问题。在这个线程上创建了一个Looper实例,它具有一个MessageQueue数据结构。Looper将处于一个无限循环中,等待读取在MessageQueue上发布的Message / Runnable实例。要将Message / Runnable添加到MessageQueue中,使用Handler。
当你创建一个Handler实例时,它将与当前的执行线程和在该特定线程上创建的Looper实例关联起来。
因此,当你通过Handler发布一条消息时,该消息将被添加到MessageQueue中,然后由Looper按照先进先出的顺序读取,并传递给目标。
new Handler().post()和View.post有所不同。
- 当你通过View.post发布消息时,你可以确保消息将被发布到UI线程的MessageQueue中,因为它内部使用了在UI线程上创建的Handler实例。
- 如果你在UI线程上创建Handler实例,并使用它在任何线程上发布消息,消息将被发布到UI线程的MessageQueue中。
- 如果你在非UI线程上创建Handler实例,并使用它发布消息,消息将被发布到非UI线程的MessageQueue中。
在Android开发中,我们经常会使用Handler来处理UI线程中的任务。根据Android官方文档,Handler可以在任何线程中创建,但是它会在创建它的线程上执行所提供的Runnable。
与之相比,在View.post方法中,Runnable始终会在UI线程中执行。
需要注意的是,在创建Handler之前,我们需要为该线程关联一个Looper。我们可以通过调用Looper.prepare()方法在创建Handler之前关联Looper,然后在Handler初始化后调用Looper.loop()方法。
虽然我经常使用Handler,但我从未使用过Looper。那么,什么时候需要使用Looper呢?编辑:忘了,我刚刚看到你的答案。解释得很好,非常清楚。
Handler和View.post的不同之处在于Runnable在不同的线程中执行。Handler可以在任何线程中创建,但Runnable会在创建它的线程中执行,而View.post始终会在UI线程中执行Runnable。在创建Handler之前,我们需要调用Looper.prepare()方法关联Looper,在Handler初始化后调用Looper.loop()方法。
Android中的Handler类是用来处理消息的,它可以将一个Runnable对象或者一个Message对象添加到其关联线程的消息队列中。在Android中,有一个叫做Looper的线程,比如UI线程,它有自己的Looper对象,用来运行线程的消息循环。当我们在UI线程中创建一个Handler对象时,它会与UI线程的Looper关联起来,所以我们通过Handler.post方法添加的Runnable对象会在UI线程上执行。
在这个代码中,使用new Handler().post(Runnable)和View.post(Runnable)方法添加Runnable对象到UI线程的消息队列中,对于这个特定的用例来说,它们大部分是一样的。但是它们是不同的:
- View.post(Runnable)方法会将Runnable对象添加到UI线程的Looper的消息队列中。
- Handler.post(Runnable)方法会将Runnable对象添加到与Handler关联的线程的Looper的消息队列中。
所以,它们的区别在于将Runnable对象添加到不同的线程的消息队列中。
以上是我对这个问题的理解,如果我有错误的地方,请纠正我。