安卓主线程之旅

不管是C++程序还是Java程序,都会有程序的入口,所有的Java应用程序都是从public static void main 开始,同样Android程序也有同样入口。

public class JavaStart{
  public static void main(String... args) {
    // The Java universe starts here.
  }
}

那么安卓APP的入口在哪里呢?

  现在就开始回答这个问题,当Android系统启动的时候,它创建一个称为ZygoteInit的进程,这个进程包含Java虚拟机和大部分公共的Class及Android SDK .当系统启动一个APP时,系统forks这个ZygoteInit进程,然后调用 ActivityThread.main()函数,所以这个就是安卓APP的入口函数,应用的入口地方。

Loopers

随着我们进一步研究,我们会发现ActivityThread成员 Looper class.从名字就可以看出它是一个无限循环,占据一个循环,另外通过观察如下代码,我们发现它有一个消息队列,用来处理消息。需要注意的我们在开发应用的时候,尽量使用message.obtain来创建消息,这样在loop循环中,我们就可以同message的recycle函数将其回放,达到循环使用,所以尽量不要使用new创建message.

void loop() {
  while(true) {
    Message message = queue.next(); // blocks if empty.
    dispatchMessage(message);
    message.recycle();
  }
}

每个Looper与一个线程绑定,而为了绑定当前的线程,你可以调用Looper.prepare .这个 loopers 储存在static ThreadLocal,获取与当前线程绑定的looper,可以调用Looper.myLooper().

我们可以这样使用Looper,HandlerThread是我自定义的一个类,你可以这样使用它。

HandlerThread thread = new HandlerThread("SquareHandlerThread");
thread.run(); // starts the thread.
类的定义如下:
class HandlerThread extends Thread {
  Looper looper;
  public void run() {
    Looper.prepare(); // Create a Looper and store it in a ThreadLocal.
    looper = Looper.myLooper(); // Retrieve the looper instance from the ThreadLocal, for later use.
    Looper.loop(); // Loop forever.
  }
}

Handlers

Handler 是looper天生的朋友,它有两个目的:

  • 从一个线程到当前Looper的消息队列
  • 处理looper 消息队列的消息,当然这个handler 必须和这个looper 绑定
// Each handler is associated to one looper.
Handler handler = new Handler(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);

你可以绑定多个hander到looper并且 looper 会传递 message到message.target.

一个简单并且流行使用 handler的方式是: 发送一个 Runnable.

// Create a message containing a reference to the runnable and add it to the looper queue
handler.post(new Runnable() {
  public void run() {
    // Runs on the thread associated to the looper associated to that handler.
  }
});

一个handler也可以通过如下方式创建!那么它的looper是谁呢?

// DON‘T DO THIS
Handler handler = new Handler();

答案就在这个Looper.myLooper() 通过这个函数
获得与当前线程绑定的Looper. 当然大多时候,你想handler绑定主线程,你可以这样来做,如下:

Handler handler = new Handler(Looper.getMainLooper());

让我们最后回到这里,APP的入口,看看它做了什么?

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().

时间: 2024-11-29 02:10:00

安卓主线程之旅的相关文章

我的编程之旅

四年前的一个雨夜,冥冥之中我选择了IT行业,从此也就开始了我大学四年的编程之旅,编程这个时而让我兴奋又时而让我苦恼的东西,到处充满BUG的世界里孕育着许多美妙,许多纠结的心悸.远离游戏,远离电影,也远离了恋爱,那时起我的世界便是整天的苦读专业基础课本,整天的面对着学校里那台老旧的电脑,BUG,BUG...,实践着课本上的理论,敲击着那早已抹去字母的键盘,我的生活里到处是忙碌着的,这苦逼的生活,转眼间过去了两年,学院让我们重选了方向,以为自己的专业功底很牛,义无反顾的选着了让许多人望洋兴叹的“嵌入

一次没有最后期限的编程之旅

今年上半年,是我工作以来最繁忙的六个月,总之遇到了最艰难的教程.最冗长的文档.最繁琐的代码以及最窘迫的合作,最终的极度疲劳成了压垮了我的最后一根稻草. 那年杭州,接连40摄氏度以上的连续高温,忽然一天39度,竟然觉得整个世界都清凉了.人,就是这么犯贱,稍有舒缓,便全然忘记曾经的抓狂. “写一个Apple Watch APP玩玩”,忽然闪过这么一个念头.这对执着于<证明论>和<集合论>的苦行者而言,浮现的不过是一次短暂的旅行. 旅行,不是迁移,抑或流浪,终究是要回归的. 记得还是在2

分享《父与子的编程之旅python》第2版中英文PDF代码+《趣学Python编程》中英文PDF代码

<父与子的编程之旅python>作者是一对父子,他们以Python语言为例,详尽细致地介绍了Python如何安装.字符串和操作符等程序设计的基本概念,介绍了条件语句.函数.模块等进阶内容,最后讲解了用Python实现游戏编程.书中的语言生动活泼,叙述简单明了. 为了让学习者觉得编程有趣,编排了很多卡通人物及场景对话,让学习者在轻松愉快之中跨入计算机编程的大门.第 2 版增加了一些说明,解释 Python 2 和 Python 3 的区别,增加了一节关于 Python 字典的内容. <趣学

安卓--子线程和主线程之间的交互实例(时钟)

.xml代码如下: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" and

在安卓主线程不能发送网络请求的解决办法

第一种方法: 在主线程中加入这段代码,强制在主线程执行网络请求 if (android.os.Build.VERSION.SDK_INT > 9) { StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); } 第二种方法: 利用安卓系统自带的异步执行,将网络请求的代码加入在里面 new Async

分布式缓存系统 Memcached 主线程之main函数

前两节中对工作线程的工作流程做了较为详细的分析,现把其主要流程总结为下图: 接下来本节主要分析主线程相关的函数设计,主函数main的基本流程如下图所示: 对于主线程中的工作线程的初始化到启动所有的工作线程前面已经做了分析,后面的创建监听socket.注册监听socket的libevent事件.启动主线程的libevent事件循环,就是接下来的内容了. 其中主要调用的函数是server_sockets,该函数从配置参数setting.inner字符串中依次提取出一个ip或者一个hostname(一

C# 子线程与主线程之间的通信

先说明一下,本人最近遇到了什么问题,就是在写写消息队列的时候,发现消息队列每次接收一个消息的时候都是创建了一个新的线程.这样就导致了消息处理的时候没有在主线程上进行,然而其中的一些步事项是要通过主线程才能操作的.这样就引出了一个子线程怎么去通知主线程要做哪些事情呢? 为了解决上面的问题我找了好的多资料,好多都是用委托,去解决了,然后我又看了我的项目通过这种beginInvoker的这种办法解决不是很好用.并不能解决的当前的问题,在这个时候我发现了SynchronizationContext对象.

分享《父与子的编程之旅python【第二版】》+PDF+源码+Warren Sande+苏金国

下载:https://pan.baidu.com/s/1hv3QvBfU7tG9WRCiSxoucA 更多资料分享:http://blog.51cto.com/14087171 <父与子的编程之旅[第二版]>高清中文版PDF+高清英文版PDF+源代码 以Python语言为例,详尽细致地介绍了Python如何安装.字符串和操作符等程序设计的基本概念. 高清中文版PDF,458页,彩色配图,带目录和书签,能够复制粘贴:高清英文版PDF,490页,彩色配图,带目录和书签,能够复制粘贴:中英文两版可以

(一)C#编程基础复习——开启编程之旅

回想当年学习编程,刚开始学习是非常艰苦的,可能是因为文科生原因,刚开始接触工科类的知识不是很擅长,上去大学第一年基本没有好好学习编程,入门C#编程基础一窍不通,也许那时年少无知,第二学期开始奋发图强,终于在编程之路越走越远,现在目前在国内BAT某家公司从事互联网内部系统开发工具的开发,趁这段时间有点空闲好好总结,复习下以前的知识,编程之路漫漫,只有不断的成长和学习,才能走得更远,不忘初心,方得始终.这里先讲几个基础,然后层层深入,尽管自己学识也不是很渊博,但是写下这些回忆,或许对自己也是有很大帮