2018-08-09 14:39:52 457浏览
Android是一个基于Linux实现的操作系统。但对于Linux内核来说,Android也仅仅只是一个运行在内核之上的应用程序,与其他运行在内核之上的应用程序没有任何区别。所以Android需要一套机制管理运行在Linux进程中的APK应用程序。很多参加Android培训的同学也需要知道这个知识点。Android内存管理包含两部分,一部分是Framework对内存的管理,一部分是Linux内核对内存管理,这两部分共同决定应用程序的生命周期。本文主要阐述Android内存管理机制的实现原理,以及在应用开发中需要注意的一些事项,最后文章总结了如何实现杀不死进程的一种方法。本文分为两部分阅读。这是本文的第二部分。
Android系统试图尽可能长时间地保持应用程序进程,但为了新建或者运行更加重要的进程,总是需要清除过时进程来回收内存。为了决定保留或终止哪个进程,根据进程内运行的组件及这些组件的状态,系统把每个进程都划入一个“重要性层次结构”中。重要性最低的进程首先会被清除,然后是下一个最低的,依此类推。
重要性层次结构共有5级,以下列表按照重要程度列出了各类进程(第一类进程是最重要的,将最后一个被终止):
1)前台进程
用户当前操作所必须的进程。满足以下任一条件时,进程被视作处于前台:
其中运行着正与用户交互的Activity(Activity对象的onResume()方法已被调用)。
其中运行着与用户交互的activity绑定的Service。
其中运行着前台Service,既该Service以startForeground()方式被调用。
其中运行着正在执行生命周期回调方法(onCreate()、onStart()或onDestory())的Service。
其中运行着正在执行onReceive()方法的BroadcastReceiver。
一般而言,任何时刻前台进程的数量都为数不多,只有当内存不足以维持它们同时运行时才会被终止。通常,设备这时候已经到了使用虚拟内存的地步,终止一些前台进程是为了保证用户界面的及时响应。
2)可见进程
没有前台组件、但仍会影响用户在屏幕上所见内容的进程。满足以下任一条件时,进程被认为是可见的:
其中运行着非前台Activity,但用户仍然可见到此activity(onPause()方法被调用)。例如,打开了一个对话框,而activity还允许显示在对话框后面,对用户依然可见。
其中运行着被可见(或前台)activity绑定的Service。
可见进程被认为是非常重要的进程,除非无法维持所有前台进程同时运行了,否则它们是不会被终止的。
3)服务进程
此进程运行着由startService()方法启动的服务,它不会升级为前台进程或可见进程。尽管服务进程不直接和用户所见内容关联,但他们通常在执行一些用户关心的操作(比如在后台播放音乐或从网络下载数据)。因此,除非内存不足以维持所有前台、可见进程同时运行,系统会保持服务进程的运行。
4)后台进程
包含用户不可见activity(Activity对象的onStop()方法已被调用)的进程。这些进程对用户体验没有直接的影响,系统可能在任意时间终止它们,以回收内存供前台进程、可见进程及服务进程使用。
通常系统会有很多后台进程在运行,所以它们被保存在一个LRU(最近最少使用)列表中,以确保最近被用户使用的activity最后一个被终止。如果一个activity正确实现了生命周期方法,并保存了当前的状态,则终止此类进程不会对用户体验产生可见的影响。因为在用户返回时,activity会恢复所有可见的状态。关于保存和恢复状态的详细信息,请参阅Activity文档。
5)空进程
不含任何活动应用程序组件的进程。保留这种进程的唯一目的就是用作缓存,以改善下次在此进程中运行组件的启动时间。为了在进程缓存和内核缓存间平衡系统整体资源,系统经常会终止这种进程。
依据进程中目前活跃组件的重要程度,Android会给进程评估一个尽可能高的级别。例如,如果一个进程中运行着一个服务和一个用户可见的activity,则此进程会被评定为可见进程,而不是服务进程。
此外,一个进程的级别可能会由于其它进程的依赖而被提高——为其它进程提供服务的进程级别永远不会低于使用此服务的进程。比如:如果A进程中的contentprovider为进程B中的客户端提供服务,或进程A中的服务被进程B中的组件所调用,则A进程至少被视为与进程B同样重要。
因为运行服务的进程级别是高于后台activity进程的,所以,如果activity需要启动一个长时间运行的操作,则为其启动一个服务会比简单地创建一个工作线程更好些——尤其是该操作时间比activity的生存期还要长的情况下。比如,一个activity要把图片上传至Web网站,就应该创建一个服务来执行之,即使用户离开了此activity,上传还是会在后台继续运行。不论activity发生什么情况,使用服务可以保证操作至少拥有“服务进程”的优先级。同理,广播接收器broadcastreceiver也是使用服务来处理耗时任务的,而不是简单地把它放入线程中。
杀不死的Service
如何让应用在手机中存活更长时间?网上各种方法可谓是千奇百怪,有些简直异想天开。
系统广播唤醒应用,比如手机开机,网络切换等
接入第三方SDK唤醒应用,比如接入微信SDK会唤醒微信
免杀白名单,比如360免杀白名单,MIUI系统免杀白名单
全家桶,应用之间互相唤醒,比如百度系,阿里系应用
两个Service互相唤醒(这个就别想了,不靠谱)
使用Timer定时器(一样不靠谱)
设计良好的应用不应该在用户不使用的时候依然保持运行。一直在后台运行不光费电费流量,还是造成系统卡顿的主要原因之一(参见上文分析)。正常的做法是优化你的应用程序,减少不合理场景的情况,除一些必要服务应用外,大部分应用不需要一直在后台保存运行状态。
有正常的做法就有不正常的做法,让应用长时间停留在用户手机中无外乎就是增加所谓的活跃用户数等一些产品指标。这对于很多公司还是很有吸引力的。
如上文所说,无论应用怎么挣扎,当处于不可见进程的情况下随时都有可能被杀死。所以使用前台进程是最有效的方法。但前台进程必须有一个Notifcation显示在通知栏中,有没有办法让应用以前台进程的方式启动同时又不显示Notifcation?方法当然有,就是利用系统漏洞:
API<18,启动前台Service时直接传入newNotifcation();
API>=18,同时启动两个id相同的前台Service,然后再将后启动的Service做stop处理
目前,QQ,微信,支付宝等知名应用都使用此方案。不过如果应用占用太多内存即使是前台进程也依然会被干掉。
这些所谓的实现进程杀不死的方案并不都是一劳永逸的方法,以牺牲用户体验为代价很有可能会激怒用户卸载你的应用,所以最好的方式还是遵循Android规范开发性能更优更合理的应用程序。
以上这篇就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持扣丁学堂,想要了解更多详情请登录扣丁学堂官网咨询或者关注微信公众号,里面有最新的扣丁学堂Android视频教程等你来看!
【关注微信公众号获取更多学习资料】