Android 主线程之旅——PSVM(public static void main)
来源:互联网 发布:如何在手机淘宝上开店 编辑:程序博客网 时间:2024/05/22 05:30
Android 主线程之旅——PSVM(public static void main)
当碰到与Android主线程交互相关的Bug时,我决定好好去看看Android的主线程究竟是怎么一回事。这篇文章就是描述我的Android主线程之旅的第一部分。
PSVM
publicclass BigBang { public static void main(String... args) { // The Java universe starts here. }}
众所周知,所有的Java程序的入口都是 public static void main()
方法。这对所有的Java 桌面程序、J2EE以及Android程序都是成立的。
当Android启动时,它会开启一个叫做 ZygoteInit
的Linux进程。这个进程是一个Dalvik 虚拟机,它会在一个线程上面加载Android SDK里面大部分的常用类,然后等待。
当Android启动一个新的Android程序时,Android系统会 fork
这个ZygoteInit
进程。接着子进程里面的线程会停止等待,然后调用ActivityThread.main()
方法。
Wikipedia上面的一个Zygote。根据Wikipedia的定义,一个 Zygote 就是一个受精卵细胞。
Loopers
在继续深入之前,我们需要来看一看Looper
这个类。
使用looper可以连续地为一个线程处理它的消息。
每一个looper都有一个消息队列(一个 MessageQueue
)。
每一个looper都有一个处理消息队列里面所有消息的loop()方法,这个方法会在消息队列为空时阻塞。
Looper.loop() 方法里面的代码类似这样:
void loop() { while(true) { Message message = queue.next(); // blocks if empty. dispatchMessage(message); message.recycle(); }}
每一个looper都会和一个线程绑定。要创建一个新的looper并将它同当前的线程绑定起来,你必须要调用Looper.prepare()
方法。这些looper都被存储在Looper 类里面的静态ThreadLocal
变量里面。你可以通过调用Looper.myLooper()
方法来获取与当前线程相关联的Looper。
当然实际情况不要这么复杂,其实HandlerThread
类已经帮你做了所有事情:
HandlerThread thread = new HandlerThread("SquareHandlerThread");thread.start();// starts the thread.Looper looper = thread.getLooper();
HandlerThread
的内部代码类似于这样:
classHandlerThread extendsThread { Looper looper; public void run() { Looper.prepare();// 创建一个Looper对象并将它保存到一个ThreadLocal 对象里面。 looper = Looper.myLooper(); // 从ThreadLocal 里面获取Looper以便后来的使用。 Looper.loop();// Loop forever. }}
Handlers
handler 天生就是 looper 的好伙伴。
一个 handler 有两个作用:
- 从任意线程发送消息给一个looper的消息队列;
- 处理相关联的looper发过来的消息。
// Each handler is associated to one looper.Handler handler = newHandler(looper) { public void handleMessage(Message message) { // Handle the message on the thread associated to the given looper. if(message.what == DO_SOMETHING) { // do something } }}; // Create a new message associated to that handler.Message message = handler.obtainMessage(DO_SOMETHING); // Add the message to the looper queue.// Can be called from any thread.handler.sendMessage(message);
你可以为一个looper关联多个handler。looper会把message发送到message.target(它就是一个handler)这里。
一个常用简单的用法就是使用handler来发送一个Runnable
对象:
//创建包含一个runnable引用的message,然后将这个message添加到这个looper的消息队列handler.post(new Runnable() { public void run() { // 这会在与handler相关联的looper对应的线程上运行 }});
一个handler也可以在没有设置looper的情况下被创建。:
// DON'T DO THISHandler handler = new Handler();
handler的无参构造函数会调用方法来获取与当前线程相关联的looper。这个时候你要注意,可能当前线程不是你的handler想关联的线程。
大部分时间,你只需要创建一个在主线程上面发送消息的handler就行了:
Handler handler = new Handler(Looper.getMainLooper());
Back to PSVM
让我们再来看看 ActivityThread.main()
这个方法。下面就是这个方法的一些内部实现:
public class ActivityThread { public static void main(String... args) { Looper.prepare(); // You can now retrieve the main looper at any time by calling Looper.getMainLooper(). Looper.setMainLooper(Looper.myLooper()); // Post the first messages to the looper. // { ... } Looper.loop(); }}
现在你知道为什么这个线程被称为主线程了吧:) .
注意: 主线程最先做的几件事情之一就是创建Application
对象,然后调用Application.onCreate()
方法。
- Android 主线程之旅——PSVM(public static void main)
- public static void main
- Java之public static void main(String[] args)
- public static void main(String[] args) 分析
- public static void main(String [] args)
- public Static void main(String[]args){
- public static void main(String[] args)
- 浅谈 public static void main(String[] args)
- 为什么main方法是public static void?
- 为什么main方法是public static void?
- 为什么main方法是public static void?
- 为什么main方法是public static void?
- 为什么main方法是public static void?
- 关于public static void main(String[] args)
- public static void main(String[] args){…}
- public static void main(String[] arg)
- 为什么main方法是public static void?
- public static void main(String[] args)
- Openstack development trend
- 程序员必须知道的10大基础实用算法及其讲解
- win8-txt文件不能默认记事本打开
- iOS-获取苹果设备信息
- test
- Android 主线程之旅——PSVM(public static void main)
- 头部购物车里不显示商品的bug
- Javascript 中的 && 和 || 使用小结
- 求助IPTABLES移植问题
- 21、MySQL-分组查询(GROUP BY)及二次筛选(HAVING)
- Django:快速搭建简单的Blog
- 《scrum实战-敏捷软件项目管理与开发》读书笔记
- 22、MySQL-对查询结果排序(ORDER BY)
- LeetCode之Pascal’s Triangle II