1.概述
Android系统的底层建立在Linux系统之上,采用软件叠层(software stack,使得层与层之间相互分离)的方式进行构建。其本质就是在标准的linux系统上增加了Java虚拟机Dalvik,并在Dalvik虚拟机上搭建了一个Javaapplication framework,所有的应用程序都是基于Java的application framework之上。
android运行时由两部分组成:Android核心库集和Dalvik虚拟机。其中核心库集提供了Java语言核心库所能使用的绝大部分功能,而虚拟机则负责运行Android应用程序。每个Android应用程序都运行在单独的Dalvik虚拟机内。
onCreate(Bundle savedInstanceState):创建activity时调用,还以Bundle的形式提供对以前存储的任何状态的访问。
onStart():activity变为在屏幕上对用户可见时调用。
onResume():activity开始与用户交互时调用。
onPause():activity被暂停或收回CPU和其他资源时调用,该方法用于保存活动状态的。
onStop():activity被停止并转为不可见阶段及后续的生命周期事件时调用。
onRestart():重新启动activity时被调用。该活动仍在栈中,而不是启动新的活动。
onDestroy():activity被完全从系统内存中移除时调用。
(1)iOS是“伪后台”,所谓的“后台驻留”并不是指“执行中的程序”,而是“最近使用过的程序”。如果你一个一个去清楚“后台驻留”的程序,就像是一笔一笔删除浏览记录中的项目一样,是没有太大意义的。一般来说,在你按下Home键后,本来的程式就会退到背景,如果它有额外的背景执行作业,超过10分钟还是会被ios中止。ios只给一部分进程留有后台运行权限,比如音乐播放之类的。苹果一直只能有一个程序在工作,其他的都会停掉,所以非常流畅(其他特殊的进程在后台跑的)。虽然说程序被停了,但是,程序并没有在内存中释放,而是继续放在内存中,这样带来的好处就是你再次打开程序的时候,会回复到你之前关闭程序的界面,程序快速的继续运行。那么,当内存中程序太多了,内存不够的时候怎么办?当内存不足的时候,iOS会依据自身判断出程序的优先级,之后清理程序占用的内存。比如音乐,应该就属于是优先级比较高的程序。iOS根据优先级,和使用次数来决定哪些程序首先清出后台。不只是简单的看时间。将程序踢出内存,就是所谓的挂起。从而释放内存,供新打开的程序使用。当然,以前一直被苹果用户给诟病的就是QQ不能挂后台,一按Home键就掉线就是这个原因(当然,苹果通过推送来解决这个问题)。
android有前台运行和后台运行之说,当你把一个程序放到后台,他是活动的,跟在前台没有区别。而且还有些系统的服务一直在运行。android大多应用没有退出的设计其实是有道理的,这和系统对进程的调度机制有关系。如果你知道java,就能更清楚这机制了。其实和java的垃圾回收机制类似,系统有一个规则来回收内存。进行内存调度有个阀值,只有低于这个值系统才会按一个列表来关闭用户不需要的东西。当然这个值默认设置得很小,所以你会看到内存老在很少的数值徘徊。但事实上他并不影响速度。相反加快了下次启动应用的速度。这本来就是android标榜的优势之一,如果人为去关闭进程,没有太大必要。特别是自动关进程的软件。 到这里有人会说了,那为什么内存少的时候运行大型程序会慢呢?其实很简单,在内存剩余不多时打开大型程序,会触发系统自身的调进程调度策略,这是十分消耗系统资源的操作,特别是在一个程序频繁向系统申请内存的时候。这种情况下系统并不会关闭所有打开的进程,而是选择性关闭,频繁的调度自然会拖慢系统。所以,论坛上有个更改内存阀值的程序可以有一定改善。 但改动也可能带来一些问题,取决于值的设定。 那么,进程管理软件有无必要呢?有的。就是在运行大型程序之前,你可以手动关闭一些进程释放内存,可以显著的提高运行速度。但一些小程序,完全可交由系统自己管理。谈到这里,可能有的朋友会问,如果不关程序是不是会更耗电。我就说说 android后台的原理,你就明白了。android的应用在被切换到后台时,它其实已经被暂停了,并不会消耗cpu资源,只保留了运行状态。所以为什么有的程序切出去重进会到主界面。但是,一个程序如果想要在后台处理些东西,如音乐播放,它就会开启一个服务。服务可在后台持续运行,所以在后台耗电的也只有带服务的应用了。这个在进程管理软件里能看到,标签是service。至于广播什么的我就不涉及了。所以没有带服务的应用在后台是完全不耗电的,没有必要关闭。这种设计本来就是一个非常好的设计,下次启动程序时,会更快,因为不需要读取界面资源,何必要关掉他们抹杀这个android的优点呢? 还有一个。为什么android一个应用看起来那么耗内存。大家知道,android上的应用是java,当然需要虚拟机,而android上的应用是带有独立虚拟机的,也就是每开一个应用就会打开一个独立的虚拟机。这样设计的原因是可以避免虚拟机崩溃导致整个系统崩溃,但代价就是需要更多内存。 以上这些设计确保了android的稳定性,正常情况下最多单个程序崩溃,但整个系统不会崩溃,也永远没有内存不足的提示出现。大家可能是被windows毒害得太深了,总想保留更多的内存,但实际上这并不一定会提升速度,相反却丧失了程序启动快的这一系统特色,很没必要。大家不妨按我说的习惯来用用这个系统。
总结
①后台程序的运行状态
IOS:分三类应用,大部分应用切换到后台会停止运行,部分应用(音乐、voip)在任务完成后也会停止,后台应用不耗cpu,但应用内存保持占用状态
Android:切换后台后应用进入onstop()状态,不是真正停止,这种状态下也不消耗cpu,部分Android应用自带后台服务,后台服务不会停止,需要消耗CPU,应用内存都会保持占用状态
②后台应用内存管理
IOS:后台应用内存保持,在新开启应用申请内存时会有一套完善机制(重要性、打开次数等)确定回收哪些应用的内存,并为新开启的应用分配足够的内存;
Android:设置内存阀值,只有低于这个值系统才会按一个列表来关闭用户不需要的东西,在内存剩余不多时打开大型程序,会触发系统自身的调进程调度策略十分消耗系统资源;每一个android都运行在一个虚拟机中,所以更耗内存
Android四大组件分别为activity、service、content provider、broadcast receiver。
5.1 activity
(1)一个Activity通常就是一个单独的屏幕(窗口)。
(2)Activity之间通过Intent进行通信。
(3)android应用中每一个Activity都必须要在AndroidManifest.xml配置文件中声明,否则系统将不识别也不执行该Activity。
5.2 service
(1)service用于在后台完成用户指定的操作。service分为两种:
(a)started(启动):当应用程序组件(如activity)调用startService()方法启动服务时,服务处于started状态。
(b)bound(绑定):当应用程序组件调用bindService()方法绑定到服务时,服务处于bound状态。
(2)startService()与bindService()区别:
(a)started service(启动服务)是由其他组件调用startService()方法启动的,这导致服务的onStartCommand()方法被调用。当服务是started状态时,其生命周期与启动它的组件无关,并且可以在后台无限期运行,即使启动服务的组件已经被销毁。因此,服务需要在完成任务后调用stopSelf()方法停止,或者由其他组件调用stopService()方法停止。
(b)使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。
(3)开发人员需要在应用程序配置文件中声明全部的service,使用标签。
(4)Service通常位于后台运行,它一般不需要与用户交互,因此Service组件没有图形用户界面。Service组件需要继承Service基类。Service组件通常用于为其他组件提供后台服务或监控其他组件的运行状态。
5.3 content provider
(1)android平台提供了Content Provider使一个应用程序的指定数据集提供给其他应用程序。其他应用可以通过ContentResolver类从该内容提供者中获取或存入数据。
(2)只有需要在多个应用程序间共享数据是才需要内容提供者。例如,通讯录数据被多个应用程序使用,且必须存储在一个内容提供者中。它的好处是统一数据访问方式。
(3)ContentProvider实现数据共享。ContentProvider用于保存和获取数据,并使其对所有应用程序可见。这是不同应用程序间共享数据的唯一方式,因为android没有提供所有应用共同访问的公共存储区。
(4)开发人员不会直接使用ContentProvider类的对象,大多数是通过ContentResolver对象实现对ContentProvider的操作。
(5)ContentProvider使用URI来唯一标识其数据集,这里的URI以content://作为前缀,表示该数据由ContentProvider来管理。
5.4 broadcast receiver
(1)你的应用可以使用它对外部事件进行过滤,只对感兴趣的外部事件(如当电话呼入时,或者数据网络可用时)进行接收并做出响应。广播接收器没有用户界面。然而,它们可以启动一个activity或serice来响应它们收到的信息,或者用NotificationManager来通知用户。通知可以用很多种方式来吸引用户的注意力,例如闪动背灯、震动、播放声音等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。
(2)广播接收者的注册有两种方法,分别是程序动态注册和AndroidManifest文件中进行静态注册。
(3)动态注册广播接收器特点是当用来注册的Activity关掉后,广播也就失效了。静态注册无需担忧广播接收器是否被关闭,只要设备是开启状态,广播接收器也是打开着的。也就是说哪怕app本身未启动,该app订阅的广播在触发时也会对它起作用。
5.4 android四大组件总结:
(1)4大组件的注册
4大基本组件都需要注册才能使用,每个Activity、service、Content Provider都需要在AndroidManifest文件中进行配置。AndroidManifest文件中未进行声明的activity、服务以及内容提供者将不为系统所见,从而也就不可用。而broadcast receiver广播接收者的注册分静态注册(在AndroidManifest文件中进行配置)和通过代码动态创建并以调用Context.registerReceiver()的方式注册至系统。需要注意的是在AndroidManifest文件中进行配置的广播接收者会随系统的启动而一直处于活跃状态,只要接收到感兴趣的广播就会触发(即使程序未运行)。
(2)4大组件的激活
内容提供者的激活:当接收到ContentResolver发出的请求后,内容提供者被激活。而其它三种组件activity、服务和广播接收器被一种叫做intent的异步消息所激活。
(3)4大组件的关闭
内容提供者仅在响应ContentResolver提出请求的时候激活。而一个广播接收器仅在响应广播信息的时候激活。所以,没有必要去显式的关闭这些组件。Activity关闭:可以通过调用它的finish()方法来关闭一个activity。服务关闭:对于通过startService()方法启动的服务要调用Context.stopService()方法关闭服务,使用bindService()方法启动的服务要调用Contex.unbindService()方法关闭服务。
(4)android中的任务(activity栈)
(a)任务其实就是activity的栈,它由一个或多个Activity组成,共同完成一个完整的用户体验。栈底的是启动整个任务的Activity,栈顶的是当前运行的用户可以交互的Activity,当一个activity启动另外一个的时候,新的activity就被压入栈,并成为当前运行的activity。而前一个activity仍保持在栈之中。当用户按下BACK键的时候,当前activity出栈,而前一个恢复为当前运行的activity。栈中保存的其实是对象,栈中的Activity永远不会重排,只会压入或弹出。
(b)任务中的所有activity是作为一个整体进行移动的。整个的任务(即activity栈)可以移到前台,或退至后台。
(c)Android系统是一个多任务(Multi-Task)的操作系统,可以在用手机听音乐的同时,也执行其他多个程序。每多执行一个应用程序,就会多耗费一些系统内存,当同时执行的程序过多,或是关闭的程序没有正确释放掉内存,系统就会觉得越来越慢,甚至不稳定。为了解决这个问题,Android引入了一个新的机制,即生命周期(Life Cycle)。