Android开发圈(ID:RainYang_WX)
作者:宇宝守护神(rainyang)个人小程序:微捷径
了解进程概念
进程是程序的一次执行,是系统进行资源分配和调度的基本单位,有自己专属的内存资源。
进程是操作系统上的概念,所以无论在PC端还是移动端都是存在的,进程在PC端上,表现为程序,比如音乐播放器,聊天软件等;在手机上,就是一个个应用软件。
进程与线程区别
先看一张图
从上面这张图,我们可以看出来,进程包含线程。一个进程里可以有多个线程,这样的一个关系。
每个进程都有一块属于自己的由操作系统分配的内存,默认的情况下,A进程的内存区域不能和其他进程共享。刚刚用了一个默认情况的描述词。说到进程间不能共享数据,这也不是绝对的。在特殊的情况下也是可以共享的,这种情况就是IPC机制。IPC机制全称叫做:inter-process communication ,即进程间通信。关于IPC机制,目前知道就好,本文不详细讨论IPC机制,后续有专门写篇文章讲述Android系统的IPC机制。
线程跟进程不一样,进程是不能共享内存,而线程可以。线程是包含于进程的。线程用的内存都是从其对应的进程那分配过来的。线程由于其容易创建,内存共享,适用并发场景等特性,常被称为轻量级进程。因为线程间可以共享数据,所以在并发编程中开常常会出现一个不小心从而导致并发问题,也就是多线程间数据不同步导致的问题。这点在多线程开发中要注意。
设置进程
在Android系统中,默认情况下,APP开发是单进程的。一般来说,关于多进程的业务需求也比较少,所以单进程完全够用。如果需要多进程的话,Android也是提供了方法来实现多进程。方法就是在Android Manifest文件中,为android 四大组件设置android:process属性。默认情况下,都是运行在同一个进程中的,默认进程名是应用包名。
举例说明:
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SecondActivity"
android:process=":second"
>
</activity>
<activity android:name=".ThirdActivity"
android:process="com.example.rainyang.demo.third"
/>
MainActivity 是运行在默认进程,进程名为应用包名:com.example.rainyang.demo;
SecondActivity 运行的进程名为:com.example.rainyang.demo:second,:是一种简写,表示在当前进程名前加上包名;
ThirdActivity 运行的进程名为:com.example.rainyang.demo.third。
上面举的例子是用四大组件之一的Activity表示的,同理,process属性在Service、ContentProvider、Broadcast中是一样的使用方式,一样的效果。
进程也是有优先级的划分的,你想啊,手机的内存就那么大,当运行多个进程(app)的时候,系统内存告急,当前正在使用的进程需要内存,怎么办?总不能不给内存,让用户没法使用吧。此时系统会根据进程的优先级来选择杀死优先级最低的进程,回收其内存,然后再把内存分配给,用户当前正在与其交互的进程。从而保证用户的正常的使用。
接下来我们看关于进程的分类。
进程分类
进程分类是依据进程的优先级高低为标准,进行的分类。下面将从优先级从高到低的顺序分别介绍各种进程。
foreground process(前台进程)
前台进程是用户正在与其交互的进程,是当前正在执行的操作所必须的进程。满足下面任何一条件的情况,其所在的进程都属于前台进程。
- 用户正在和Activity组件交互,并且Activity的onResume回调正在执行。Activity组件所属的进程为foreground process。
- BroadcastReceiver组件的onReceived()方法正在执行。其所在进程为foreground process。
- Service服务的onCreate()方法、onStart()方法、onDestroy()这三个方法中,如果有一个方法正在执行。此刻,其所属进程为foreground process。
前台进程是优先级最高的,一般来说,系统不会kill它,回收它的内存。你想啊,前台进程是用户正在使用操作的进程,突然让系统回收了,那用户体验得多糟糕。对于前台进程它一般是系统为其服务的进程,正式因为前台进程需要内存,系统才会去kill其他进程,回收内存,来满足它。
通过上面满足前台进程的几种情况,可以发现,这些情况都是和Android四大组件有关系的。再看看之前说到的设置多进程的方式,是在四大组件中通过process属性来设置。这些都是遥相呼应的。一定程度上可以理解为,四大组件就代表和实现了APP进程。
Visible process(可见进程)
可见进程是正在做一些用户关心的事,它的优先级虽然比前台进程优先级低,但是从它的描述词——“用户关心” 就可以看出,不能轻易杀死它,不然用户心理肯定不爽。当满足下面任一情况,表示其所在进程为可见进程:
- Activity可见,但是并没有在前台和用户交互(该Activity的onPause回调被调用),这怎么理解呢?你想想这样一种情况,Activity上面出现一个弹窗,此刻Activity是可见的,但是当前用户的关注交互点是弹窗。
- 通过调用Service的startForeground()方法,开启一个前台服务。
- 正在host一个系统用于用户注意的特定功能的服务,例如动态壁纸,输入法服务等。
这种进程,优先级也比较高,一般不轻易杀死。
Service process(服务进程)
当Service组件调用startService()方法来启用一个服务时,该服务所属进程为服务进程。尽管服务进程不会像前台进程,可见进程那样直接对用户可见的,但是在服务进程中经常会用用户所关心的一些事,比如后台网络数据的上传下载逻辑。所以除非内存不够用了,一般不会在内存够用的情况下去杀死服务进程。
已经运行了很长时间(例如30分钟或更长时间)的Service可能会降级,以允许其进程下降到下面描述的缓存LRU列表。 这有助于避免出现内存泄漏或其他问题的长时间运行服务占用大量RAM而导致系统无法有效使用缓存进程的情况。
Cached process(缓存进程)
缓存进程是优先级最低的进程,当其他地方需要内存的时候,系统会优先考虑杀死该进程。(真可怜。。),杀死该类进程对用户体验不会造成影响。
一般来说,系统中会有多个缓存进程,目的是在应用间切换的起到更有效切换的作用(缓存嘛,备胎既视感),并根据系统需要,定期的清理最老的缓存进程。系统在所有的缓存进程都杀死回收内存后,还不满足所需要的内存,就会选择向服务进程下手。
小结
通过上面对几种进程类型的理解,开发者就可以根据需求,把逻辑放在合适的进程中,避免重要业务逻辑放进低优先级的进程中,从而导致服务被杀死,用户体验不好,这种情况。
IPC
IPC(inter-process communication) 进程间通信,文章开头有提到过。其机制的作用是为了满足多进程间通信的需求。Android系统中,多进程通信的方式有Binder、AIDL(内部也是Binder)、Socket、ContentProvider等等。关于IPC机制的实现,后面的文章在详细讲解。
创作不易,觉得还不错的话,就点个"赞"鼓励下吧!