【生命周期】进程和四大组件
进程是一个比较抽象的概念,它可以被翻译成一个程序的执行过程的描述。通过进程,程序能够不受外界干扰的按照期待的想法运行。
大多数应用(不管是windows还是Linux),它们常常以main函数作为程序的起点,也是一个进程的开始。
习惯了这种方式开发的开发者可能在刚开始面对Android开发的时候会有疑惑,为什么Android应用开发要从四大组件(Activity/Service/ContentProvider/Broadcast)学起?
事实上四大组件正是Android为了简化开发者的开发而提出来的概念。
Activity: 可以显示用户界面,用户可以与之产生交互
Service:没有用户界面,但是有前台和后台的概念
ContentProvider:用于提供一些数据给其他应用(自己或自己所在的进程是服务方)
BroadCast: 可以接受期待的广播(一旦接收,可以处理一些事情)
以上四个组件正常情况都是在主线程运行的,主线程又叫UI线程,顾名思义,用户触摸产生的反馈,绘制的执行都发生在这个线程。
所以一旦有一个操作是比较耗时的,主线程就会出现“卡顿”的状态。当超过一定时间,系统将认为应用已无法响应,会弹出无响应对话框以使用户可以选择强制关闭应用。
所以说在以上几个控件内部,要小心处理有关耗时任务的调用。
既然有主线程,也就是非主线线程。因为Android应用程序运行在虚拟机中(ART),所以应用在启动时除了UI线程,同时也有一些其他的线程同时产生
比如 GC线程用来处理垃圾回收、Binder线程用来进行进程间通信(Binder比较复杂,初学者可以先跳过)。
当然,开发者也可以自己创建线程(new Thread)来创建一个线程,不过Android中有很多已经封装好的类来让你更好的开发(HanderThread,AsyncTask 等)。
下面接着回到Android的进程和Android四大组件的关系。
首先,一个Android程序的执行过程如果从应用端的角度(相对于系统端system_server),它开始的时间是在ActivityThread的main方法
注意ActivityThread不是一个线程类,而是一个普通的类,只是它“恰好”是程序的起点。
而main方法中执行的内容也相当简单
以下是简化后的源码:(源码来自https://github.com/android/platform_frameworks_base/blob/master/core/java/android/app/ActivityThread.java)
public static void main(String[] args) {
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
如果对Handler机制比较了解的话大致已经知道这是在做什么了,
首先建立主循环,代表它是主线程。
然后创建一个AcitivityThread对象,也可以说明它其实是应用唯一的实例。
接着,thread.attach(false)动作是为了和系统服务建立联系,尤其是ActivityManagerService(简称AMS)
因为系统所有的组件都是收到AMS的管控,此处进行attach目的也是可以为了未来能够收到AMS交给的任务或获取答复。
此时可以先透露一点,Android应用程序和系统进程(AMS所在的进程)在组件的启动或销毁等上面是CS架构,也就是客户端服务端的模式。Android使用了Binder来实现了这种模式。
同时也意味着应用程序的很多想法(比如打开一个Activity,启动一个Service)都需要得到AMS的同意。这样的话,AMS可以对各个组件进行控制从而保证了多任务运行能够顺利进行。
下一步就是Looper.looper()也就是程序的大循环开始执行,后续主线程的处理模式就是(等待-收到消息-执行任务-等待)这样一直运行下去直到进程被销毁。
但是,应用虽然进入了循环,但是现在好像没有任何组件在运行,事实上并不是这样。
可以考虑这样的场景,用户点击了Launcher上的你的应用图标,你的应用随之启动,你在AndroidManifest.xml文件里定义的MainActivity显示在了界面中。
而让你MainActivity启动的正是Launcher,它通过某种方式(访问PackageManagerService)来得到了你的指定了CATEGORY_LAUNCHER分类的Activity也就是MainActivity.
从而调用startActivity(intent)来启动了你的activity.
同时也要说明一点,Launcher调用了startActivity的时候有可能你的应用进程还没创建(刚才的main方法还没执行),那么系统(AMS)就会判断到这一点于是先通过startProcess的方法先启动进程,然后根据刚才thread.attcah(false)后的ApplicationThread(应用端的存根)来执行AMS允许的动作scheduleLaunchActivity[ActivityThread.java中]。
随后,new Activity,Activity.onCreate,Activity.onStart等生命周期都会进行下去,于是,Android应用进程与组件的关系由此建立起来。
注:关于Activity启动的过程和生命周期将会在接下来的博客中较为详细的讲述
参考文档: