zygote进程

Android系统是基于Linux内核的,而在Linux系统中,所有的进程都是init进程的子孙进程,也就是说,所有的进程都是直接或者间接地由init进程fork出来的。Zygote进程也不例外,它是在系统启动的过程,由init进程创建的。

一个Android的App进程的创建过程,是由 init进程 -> zygote进程 -> system_server进程 -> App进程。

zygote进程是运行app_main.cpp文件。在main函数中,会创建一个AppRuntime(AppRuntime是继承于AndroidRuntime)对象,所以一个应用拥有一个虚拟机实例,然后调用它的start方法。

start方法:

  • 创建并启动虚拟机
  • 注册JNI服务
  • 向Android虚拟机注册Android native处理函数
  • java层Zygote初始化处理

Zygote初始化:

  1. 调用registerZygoteSocket()注册套接字,用来和ActivityManagerServer通讯,接收新的Android应用程序运行请求。            创建LocalServerSocket实例(本地Socket服务端)接收生成新Android进程的信息,一个应用进程通过Binder请求SystemServer进程,SystemServer进程发送socket消息给Zygote进程。
  2. 调用preloadClasses()和preloadResource()来加载应用Framework使用的类与资源。                                                              Zygote对公共类与资源进行预加载,当应用程序启动时只需要加载自身特有的类与资源就行了,提高了应用软件的启动速度。
  3. 调用startSystemServer()运行SystemServer进程,来启动各种服务。                                                                              PackageManagerService和ActivityManagerService, 都是由SystemServer进程启动。
  4. 调用runSelectLoopMode()来循环监听,进入一个无限循环,socket接口等待ActivityManagerService请求创建新的进程。
  5. 每个应用都会持有一个ART实例。

SystemServer

SystemServer进程是Android系统的核心之一,大部分Android提供的服务都在该进程中,SystemServer中运行的进程公共有六十多种,介绍下重要的几个service;

  • AMS(ActivityManagerService)->ActivityManager                                                                                                  ActivityManagerService是整个Android Framework框架中最为核心的一个服务,用户应用程序的生命管理都是由它负责的。统筹管理着android的四大组件;统一调度各应用进程
  • PackageManagerService -> PackageManager                                                                                                                        包括对软件包的解包,验证,安装以及升级等等,不能安装.so文件的问题,应该先从这块着手分析原因。
  • WindowManagerService -> WindowManager -> PhoneWindowManager                                                                                和ActivityManagerService高度粘合;窗口管理,这里最核心的就是输入事件的分发和管理。

应用启动过程:

ActivityThread

ActivityThread就是主线程或UI线程,ActivityThread的main方法是整个APP的入口。

public final class ActivityThread {//... final H mH = new H();final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();final ApplicationThread mAppThread = new ApplicationThread();  private class ApplicationThread extends ApplicationThreadNative {    //...  }private class H extends Handler {//...}//...}

Activity信息全部被存储在ActivityThread的成员变量mActivities中。mServices则保存了所有service的信息。

    final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();

ActivityThread有三个重要的类,Instrumentation、H和ApplicationThread

  • mInstrumentation是Instrumentation类的对象,Instrumentation类为ActivityThread的一个工具类,在ActivityThread中初始化,一个进程只存在一个Instrumentation对象,在每个Activity初始化时,会通过Activity的Attach方法,将该引用传递给Activity。Activity所有生命周期的方法都有该类来执行。最后mInstrumentation调用了Application的onCreate方法。
  • H继承于Handler,mH负责处理ApplicationThread发送到消息队列的消息,Activity的生命周期都是依靠主线程的Looper.loop,当收到不同Message时则采用相应措施。
  • ApplicationThread是ActivityThread的内部类,ApplicationThread内部继承自Binder并实现IApplicationThread接口。Binder是C/S结构,Binder是Service,AMS是Client,ApplicationThread主要用于应用进程和AMS进程间通信,并用于AMS的调用,通过H类将消息发送到消息队列,然后进行相应的操作。

为什么App进程做服务端呢?

仔细想想,Activity的生命周期回调是谁调用的啊。肯定不是app本身控制,而远程服务通过监听到一系列的操作发起周期回调,AMS持有App的proxy,这个代理的协议是IApplicationThread,于是AMS监控系统需要onResume,则通过proxy发起IApplicationThread的onResume,也就是通知服务去执行onResume。所以这里作为Binder理解IPC,服务端就是客户端App而不是AMS,AMS作为请求端,持有App进程的代理。

    public static void main(String[] args) {//....//创建Looper和MessageQueue对象,用于处理主线程的消息Looper.prepareMainLooper();//创建ActivityThread对象ActivityThread thread = new ActivityThread(); //建立Binder通道(创建新线程)thread.attach(false);Looper.loop(); //消息循环运行throw new RuntimeException("Main thread loop unexpectedly exited");}
private void attach(boolean system){...final IActivityManager mgr = ActivityManager.getService();try {//将ApplicationThread这个Binder交给了ActivityManagerServicemgr.attachApplication(mAppThread);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}...BinderInternal.addGcWatcher(new Runnable() {@Override public void run() {if (!mSomeActivitiesChanged) {return;}Runtime runtime = Runtime.getRuntime();long dalvikMax = runtime.maxMemory();long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();if (dalvikUsed > ((3*dalvikMax)/4)) {if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)+ " total=" + (runtime.totalMemory()/1024)+ " used=" + (dalvikUsed/1024));mSomeActivitiesChanged = false;try {mgr.releaseSomeActivities(mAppThread);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}}});...
}

主线程(ActivityThread)的初始化:

  1. 开启消息循环。调用Looper.prepareLoop() Looper.loop(),开启主线程的消息循环,以便于ApplicationThread调用ActivityThread中的生命周期方法。
  2. 通知ActivityManagerService。调用ActivityThread.attach()方法,attach()方法在调用了attachApplication()将ApplicationThread这个Binder交给了ActivityManagerService,意味着ActivityManagerService可以通过ApplicationThread控制我们的应用,建立了服务器端对客户端的通信渠道。
  3. 添加GCWatcher。在attach()方法中,添加了监听dialvik内存使用情况得监听者GcWatcher,当内存使用超过总容量的3/4,则打印Log进行记录,并且调用ActivityManagerService的releaseSomeActivities()进行内存释放操作,以防止内存溢出导致应用崩溃。

attach()方法在调用了attachApplication()之后,经过一系列操作,最后调用了ApplicationThread的bindApplication()方法,bindApplication中通过消息机制,sendMessage到ActivityThread,handleMessage调用了ActivityThread的handleBindApplication()。通过反射创建了Application对象,然后onCreate创建activity。

 private void handleBindApplication(AppBindData data) {//创建appContext final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);try {// If the app is being launched for full backup or restore, bring it up in// a restricted environment with the base application class.//通过反射创建Applicationapp = data.info.makeApplication(data.restrictedBackupMode, null);mInitialApplication = app;try {//调用Application的onCreate方法mInstrumentation.callApplicationOnCreate(app);} catch (Exception e) {}}
}public void callApplicationOnCreate(Application app) {app.onCreate();}

总结:ActivityThread通过ApplicationThread和AMS进行进程间通讯,AMS接受 ActivityThread的请求后会回调ApplicationThread中的Binder方法,然后ApplicationThread会向H发送消息,H收到消息后会将ApplicationThread中的逻辑切换到ActivityThread中去执行,即切换到主线程中去执行。

Handler 线程间通信

从上面我们得知Activity的生命周期都是依靠主线程的Looper.loop,主线程Handler收到不同Message时则采用相应措施。接下来介绍Handler。

Handler作用:

进行子线程与主线程之间的通信。子线程可以通过Handler来通知主线程进行UI更新。

根据Looper.loop()源码可知里面是一个死循环在遍历消息队列取消息,queue.next()阻塞方法,从队列中获取消息。

    public static void loop() {final Looper me = myLooper();......for (;;) {//获取消息队列中的消息Message msg = queue.next(); // might block....//然后分发消息到Handler的处理中msg.target.dispatchMessage(msg);...//释放消息msg.recycleUnchecked();}}

Android在子线程更新UI的三种方式

 new Handler(mContext.getMainLooper()).post(new Runnable() {@Overridepublic void run() {// 在这里执行你要想的操作 比如直接在这里更新ui或者调用回调在 在回调中更新ui}
});

常见常用的post()类方法汇总:

  • post(Runnable)
  • postAtTime(Runnable,long)   System.currentTimeMillis() + 100000 在设定的目标时间post
  • postDelayed(Runnable long)    延迟多少时间再post
((Activity) context).runOnUiThread(new Runnable() {@Overridepublic void run() {// 在这里执行你要想的操作 比如直接在这里更新ui或者调用回调在 在回调中更新ui}
});
private Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what) {case ACTIVENUMBER:MaintainProtos.ActiveNumber activeNumber = (MaintainProtos.ActiveNumber) msg.obj;break;}}
};Message msg = Message.obtain();msg.what = ACTIVENUMBER;msg.obj = activeNumber;mHandler.sendMessage(msg);

常见常用的send类方法汇总:

  • sendEmptyMessage(int)
  • sendMessage(Message)
  • sendMessageAtTime(Message,long)
  • sendMessageDelayed(Message,long)

Handler内部如何获取到当前线程的Looper?

ThreadLocal。ThreadLocal可以在不同的线程中互不干扰的存储并提供数据,通过ThreadLocal可以轻松获取每个线程的Looper。当然需要注意的是①线 程是默认没有Looper的,如果需要使用Handler,就必须为线程创建Looper。我们经常提到的主线 程,也叫UI线程,它就是ActivityThread,②ActivityThread被创建时就会初始化Looper,这也是在主 线程中默认可以使用Handler的原因。

系统为什么不允许在子线程中访问UI?

这是因为Android的UI控件不是线程安全的,如果在多线程中并发访问可能会导致UI控件处于不可预期的状态,那么为什么 系统不对UI控件的访问加上锁机制呢?缺点有两个: ①首先加上锁机制会让UI访问的逻辑变得复杂 ②锁机制会降低UI访问的效率,因为锁机制会阻塞某些线程的执行。 所以最简单且高效的方法就是采用单线程模型来处理UI操作。

Looper.loop为什么不会阻塞主线程?

Activity的生命周期就是依靠Looper.loop(),Looper.loop() 不断地接收事件、处理事件,每一个点击触摸或者说Activity的生命周期都是运行在 Looper.loop() 的控制之下。所以不存在主线程会被Looper.loop方法阻塞。

Handler优化:

实现静态内部类:实际项目中Handler很少采用上面匿名类的实现方式,因为会造成内存泄漏,大部分采用静态内部类、建一个单类或者在onDestroy方法中removeCallbacksAndMessages。

使用HandlerThread:Loop主线程已经有了,不需要我们自己创建,但是子线程默认是没有开启消息循环的。需要用到Looper.prepare()和Looper.loop(),当然也可以用到我们上面的实现方式传回主线程,但是这样做会增加主线程的工作量。

HandlerThread:本质上就是一个普通Thread,只不过内部建立了Looper。

public class MainActivity extends AppCompatActivity {private HandlerThread myHandlerThread ;private Handler handler ;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//1、创建一个线程,线程名字:handler-threadmyHandlerThread = new HandlerThread( "handler-thread") ;//2、开启一个线程myHandlerThread.start();//3、在这个线程中创建一个handler对象handler = new Handler( myHandlerThread.getLooper() ){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);//这个方法是运行在 handler-thread 线程中的 ,可以执行耗时操作Log.d( "handler " , "消息: " + msg.what + "  线程: " + Thread.currentThread().getName()  ) ;}};//在主线程给handler发送消息handler.sendEmptyMessage( 1 ) ;//在子线程给handler发送数据new Thread(new Runnable() {@Overridepublic void run() {handler.sendEmptyMessage( 2 ) ;}}).start() ;}@Overrideprotected void onDestroy() {super.onDestroy();//4、释放资源myHandlerThread.quit() ;}
}

因为最后执行了quit()操作,所以内存泄漏的问题也得到解决。

Android—ActivityThread与Handler相关推荐

  1. Android中的Handler

    当我们在处理下载或是其它须要长时间运行的任务时.假设直接把处理函数放在Activity的OnCreate或是OnStart中.会导致运行过程中整个Activity无响应,假设时间过长,程序就会挂掉. ...

  2. 【Android 异步操作】Handler 机制 ( Android 提供的 Handler 源码解析 | Handler 构造与消息分发 | MessageQueue 消息队列相关方法 )

    文章目录 一.Handler 构造函数 二.Handler 消息分发 三.MessageQueue 消息队列相关函数 一.Handler 构造函数 一般使用 Handler 时 , 调用 Handle ...

  3. Android进阶——深入浅出Handler(一)

    Android进阶--深入浅出Handler(一) 在学习Handler之前,首先要学习一些基本概念,这将对之后的学习有所帮助. 主线程:Main Thread,又叫UI线程(UI Thread).A ...

  4. Android 系统(59)---Android开发:Handler异步通信机制全面解析(包含Looper、Message Queue)

    Android开发:Handler异步通信机制全面解析(包含Looper.Message Queue) 前言 最近刚好在做关于异步通信的需求,那么,今天我们来讲解下Android开发中的Handler ...

  5. Android消息机制Handler用法

    这篇文章介绍了Android消息机制Handler用法总结,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 1.简述 Handler消息机制主要包括: Messa ...

  6. 在Android中使用Handler和Thread线程执行后台操作

    在 Android中使用Handler和Thread线程执行后台操作 对于线程的控制,我们将介绍一个 Handler类,使用该类可以对运行在不同线程中的多个任务进行排队,并使用Message和Runn ...

  7. Android代码(Handler的运用),HttpURLConnection的应用,将url图片地址转换成图片。

     1 布局文件, <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xml ...

  8. Android消息机制(Handler机制) - 线程的等待和唤醒

    我们都知道,Android的Handler机制,会在线程中开启消息循环,不断的从消息队列中取出消息,这个机制保证了主线程能够及时的接收和处理消息. 通常在消息队列中(MessageQueue)中没有消 ...

  9. android studio 定时器,Android定时器和Handler用法实例分析

    本文实例讲述了Android定时器和Handler用法.分享给大家供大家参考.具体分析如下: 一.环境: 主机:WIN8 开发环境:Android Studio 二.定时器使用示例: 初始化: //定 ...

最新文章

  1. 打字游戏--飞机大战
  2. 如何解决…has been modified since the precompiled header… was built的问题
  3. c# enum 解析
  4. 如果服务器开机显示NObootable,电脑不能开机提示No bootable device怎么办?
  5. 图解TCP四次握手断开连接
  6. SDNU 1171.合并果子(区间dp)
  7. css animation动画完成后隐藏_css3动画简介以及动画库animate.css的使用
  8. 网易资深Java架构师:java数组对象转为list集合
  9. run as date怎么用_熟词僻义 | date是一种什么水果?
  10. 问题:连接查询和子查询的区别和连接及优劣?
  11. 用友与中国互联网协会签署战略合作 共推企业互联网转型
  12. 目前最新传智播客郭永锋最新工作室2018Java培训项目实战(完整)
  13. mysql获取纽约时间_如何在脚本中处理MySQL时区
  14. 【Python数据分析——使用matplotlib制作南丁格尔玫瑰图】
  15. 波菲那契数列公式_斐波那契数列为什么那么重要,所有关于数学的书几乎都会提到?...
  16. 安徽工贸职业技术学院计算机比赛,放飞青春,不负韶华!《追梦》——安徽工贸职业技术学院2019年宣传片...
  17. 00 石锅土鲫鱼项目导语
  18. DRC的报错类型及其对应的规则
  19. 四种软件架构,看看你属于哪个层次
  20. 【OpenGL 学习笔记03】点画多边形

热门文章

  1. 怎样将计算机添加桌面快捷方式,Win10系统下如何将程序快捷方式添加到桌面上?【图文教程】...
  2. php 判断update返回为0_PHP empty函数判断0返回真还是假
  3. 福师计算机辅助设计1 ps 在线作业二,福师《计算机辅助设计1(PS)》在线作业一100分答案...
  4. php5.4开启opcache,windows下php5.6启用opcache
  5. winscp登陆windows服务器_基于OpenSSH+WinSCP完成Windows服务器之间的文件传输
  6. 数据挖掘 python roc曲线_利用scikitlearn画ROC曲线实例
  7. 这个陶瓷电阻烙铁架不错哦,最新一期的电子趣事分享给大家
  8. 电子设计竞赛电源题(1)-电源题简介
  9. 机器人是如何群居生活的?
  10. 模电这么学,谁还会说不懂晶体管?