您好,欢迎访问三七文档
Android疯狂笔记bingbingzi2014年02月28日14:32浏览(2169)收藏(260)评论(9)分享前言最近接触android有一段时间了,在开发过程很想总结一些经验和体会写下来,但发现android实在博大精深,有种心有余而力不足的感觉。最近有时间看了几本书,刚好把我之前的开发中碰到的疑惑解决了。于是想把自己学到的一些andriod设计思想和一些比较有特点的坑记下来,一方面便于自己以后再回顾,另一方面希望有助于一些新入门android的童鞋。最后再说明下,本文不会涉及到具体的开发代码,重在android的设计思想和一些比较容易忽视的点。请有需要再往下阅读。总体架构和设计思想先从andriod总体架构入手。andriod包括应用层,框架层,运行层,核心类库,硬件抽象层,Linux内核。整体架构如下:应用层就是我们开发的app运行的一层。框架层是andriod系统最核心的部分,集中体现了andriod系统的设计思想。我们app应用到的最常用的窗口管理服务,通话管理服务,键盘输入管理服务等。有些组件服务不一定在你的代码显式调用,而是由基类帮你调用。比如Activity调用组件管理服务。所有系统服务都寄宿在系统核心进程中,在运行时,每个服务都占据一个独立的线程,彼此间通过进程间的通信机制(IPC)发送消息和传输数据。运行时依赖Dalvik虚拟机,Dalvik是专门为高端设备而优化设计的。它没有采用基于栈的虚拟机架构,而是采取了基于寄存器的虚拟机架构设计。基于寄存器的虚拟机,执行效率会更好,更能发挥高端设备的优势。Dalvik采用了.dex作为其一次编译的中间文件,众所周知,在andriod应用的编译过程中,会先生成若干个.class文件,然后再统一转换为.dex文件。在转换过程中,andriod会对部分.class文件中的指令做转义,使用dalvik特有的指令集OpCodes来替换,以提高执行效率,同时,.dex会整合多个.class文件中的重复信息,并对冗余部分做全局的优化,合并重复的常量定义,使得最终的.dex文件更加简洁和小。剩下的就是android提供的核心类库和硬件抽象层。核心类库里面很多都采用优秀的第三方类库,比如sqllite做本地数据库存储,openGL用来3D绘图等。看完总体架构,有人会问,大部分系统都是采用分层的思想设计的,android系统有什么特别之处,主要的设计思想有哪些呢?1.平台的开放性和兼容性。android是一个开发的平台,可以运行在各种设备环境下。君不见越来越多的设备开始搭载android系统,比如路由器,电视机,机顶盒,手表等等。这些设备也升级为智能***,档次顿时上升几个档次。可以预见的以后越来越多的电子设备会集成android系统,到时离物联网真的不远了。android要支持各种设备,最大的挑战就是兼容性,即兼容不同硬件的设备,屏幕尺寸,外设,语言环境等。android是如何做到这点呢?首先,在底层,android架设在linux之上,linux具有强大的移植能力,保证了android可以在不同的硬件环境中运行。而在上层,android为应用提供了很多增强兼容性的机制,比如基于资源目录的应用资源体系。2.基于组件的设计android的应用时高度组件化的,开发者只要按照组件开发规范,编写一个一个组件,然后再配置文件中加以描述,android系统就会统一调度这些组件。各个android应用,只有明确的组件边界,而不再有明确的进程边界和应用边界。android四大组件,界面组件Activity,服务组件Service,数据源组件ContentProvider以及触发器组件BroadcastReceiver。每个android应用,都是由这四大组件共同搭建而成。这种基于组件的设计也称为基于MashUp的设计,其核心是组件,应用边界,进程边界和网络边界都变得模糊且不重要了。在android中,组件执行时的聚合单元是任务,每个任务都有若干个界面组件对象构成,这些组件可能来自不同的应用,运行在不同的进程,他们彼此独立,无须关注具体调用和被调用者的具体实现细节。组件间的数据传输,都是通过消息,进程间的通信模型等序列化数据传输的方式来进行,而不是通过指针传递,这使得andriod天生就具备了跨进程的特性。四大组件相关界面组件了解界面组件Activity的继承结构,就可以从另外一个角度来理解界面组件。Activity类派生自Context类,Context类提供了应用运行的基本环境,是各组件和系统服务通信的桥梁。Context是个抽象类,android.app.ContextImpl派生实现了它的抽象接口,ContextImpl对象会与android框架层的各个服务(包括组件管理服务,资源管理服务等)建立远程连接,通过IPC机制和这些服务进行通信。服务组件有两种角色,一个是功能调度者,一个是功能提供者。功能调度者就只是接受服务请求,然后处理请求,处理流程如下:功能提供者还需要提供数据给调用者,这里有个绑定的过程。具体处理流程如下:android的触发器组件应该是最简单的组件了,工作方式上更接近函数,而不是对象,在OnReceive方法执行完后,就结束了其生命周期。和所有组件一样,触发器组件也是在应用进程的主线程中被构造,所以执行OnReceive方式必须是同步且快速的,否则会阻塞与用户的当前进程。组件连接模型:进程模型和进程托管每个android应用都使用包名作为唯一标识,在同一系统中,不能安装两个包名相同的应用。在android应用运行时,系统会为其分配一个进程,默认情况下,该应用进程名和该应用的包名保持一致,以此来保证进程命名的唯一性。在默认配置中,应用中的组件都会在该应用进程的主线程中构造并运行。在android中,每个组件可以通过配置文件的组件配置项android:process属性,将该组件部署到其他应用进程中运行。如果android:process的值以冒号开头,说明是一个私有进程,仅能放置本应用的组件,其他应用无法共享该进程空间;如果该值以小写字母开头,说明是一个共享进程,可以承载来自不同应用的组件,大部分非原生的应用都是使用的私有进程。如果一个应用被分配到两个进程,进程模型如下:每个应用进程都有独立的应用环境对象,彼此不能互通。属性android:multiprocess也是用于控制组件的进程模型。该值默认为false,表示该组件的对象构造和运行在于和该应用相关联的应用进程中,在这种配置下,如果组件被第三方应用调用,就会启动两个进程:第三方应用所在进程和该组件所在进程。为了节省进程开销,可以配置为true,此时,应用会将该组件“嫁”出去,当任何一个第三方应用调用该组件时,都会在这个第三方应用进程中构造一个组件对象。这种模型也有一个弊端,即该组件在系统中会存在多个对象。在android中,应用进程的构造与销毁都是由系统全权掌握的,这种模式就是进程托管。android为什么要进程托管呢?一方面是为了简化编程模型。开发者不需关注进程生命周期的细节,只需要专心处理组件本身的逻辑。另一方面是为了全局调度以及优化进程对系统资源的使用。android是一个多任务系统,为了能在更多的移动设备中运行,android并不支持虚拟内存(这需要一定的硬件支持)。如果有虚拟存储的支持,就可以在进程过多占用内存过多的时候,将部分内存数据移到外存储设备中暂时存储。没有虚拟存储的支持,android只能通过终止进程的方式去换取更多空间。这就要求系统对所有进程的生命周期都有明确的了解和绝对的控制权。有了进程的托管,就有了进程的回收,应用本身是没有办法杀掉进程,只有等待系统的回收,或者用户手动通过系统提供的进程结束界面杀掉进程。android对应用进程的回收有以下几个策略:1.尽量延长进程的生命周期,在资源允许的范围,尽量不回收已创建的进程。2.组件进程按照优先级从低到高进行回收。其中前台进程和可视进程的优先级要高于服务进程和后台进程。3.同等优先级的进程,越近被使用的越晚被回收。在组件被回收前,android会先调用Actvity.onSaveIntanceState函数,将界面中的状态序列化到一个android.os.Bundle对象中,保存到系统的核心进程内,谨防由于应用进程被销毁而导致数据丢失。界面组件的生命周期很重要,很多文章都有介绍。我这里也把这个图贴下来,以备不时之需查看。服务组件的生命周期:处于绑定状态的服务组件通常不会被回收,所以绑定服务用完需要解绑,否则不会被回收掉。界面组件栈和运行模式任务中的界面组件对象,是按照栈的形式进行组织的,每个任务都由一个界面组件栈构成,在标准的栈模型下,组件对象只能够进行进栈和出栈操作。可以通过配置运行模式来改变这种模式:android界面组件的运行模式,包括:standard,singleTop,singleTask,singleInstance.默认情况下,运行模式是standard,几个运行模式最主要的区别在于是否复用已存在对象和任务是否跳转。运行模式为singleTop的界面组件仅在作为栈顶组件时才可能复用,因此,同一界面组件在系统中还是会存在多个组件对象,而运行模式为singleTask和singleInstance的界面组件,在整个系统中仅会有一个组件对象存在。运行模式为singleTask和singleInstance的界面对象仅可能作为任务的根组件存在,singleTask和singleInstance的唯一区别是,模式为singleInstance的组件,其所在任务中包含只包含这个组件对象,不会再有其他组件对象。singleTask和singleInstance适合于消耗内存过多的单实例界面组件。由于他们仅作为根组件存在,所以他们不适合其他组件调用这些组件,且需要回调返回值的情况。即调用方采用activity.startActivityForResult方式调用,这个时候在onActivityResult是收不到返回值的。几种运行模式,对应的任务和界面组件栈如下:除了设置组件的运行模式,还可以通过动态配置Intent对象的Activity.FLAG_ACTIVITY_NEW_TASK标志位来改变运行界面栈。通常情况下这个标志位会让实现组件作为任务根组件构造新的任务来容纳它,即效果和singleTask差不多。但如果该实现组件的android:taskAffinity已被设置,他会寻找具有同样任务名的任务是否存在,如果存在,就不会再构造新的任务,而是直接跳到该任务中。android控件android的控件都派生自android.view.View类,android中有一类重要的控件,称为容器控件,通过容器控件,可将交互界面上的各个控件对象组织成控件树,上层的父控件会负责其下层子控件的排列和绘制,并将交互事件自上而下传递到子控件中。每棵控件树,都会有一个android.view.ViewParent对象与其根控件绑定,该viewParent对象是整棵控件树的交互事件的控制枢纽。它会负责将用户操作产生的交互事件传递到控件树的根控件,进而自顶而下进行传播。控件树中的每个子控件对象,都会包含执行该ViewParent对象的指针,当子控件对象的焦点,尺寸等控件属性发生改变时,会通知该控件树的ViewParent对象,由ViewParent对象统一向下分发该事件。当位于控件树上层的父控件收到交互事件后,会先行判定该事件的目标事件对象,如果该事件正是自己需要的,则会截获事件进行处理,否则就尝试将事件向下分发给对应的子控件。事件函数的返回值是控制事件传播的重要手段,如果事件函数返回true,则说明该控件已经接收并完成了该事件的处理,事件无需再传递。窗口机制android的窗口机制,是为了将用户与界面的交互传递到对应的控件中去。窗口机制的核心是窗口管理服务(WindowManagerService),它负责管理所有交互界面的控件树,并将
本文标题:android笔记
链接地址:https://www.777doc.com/doc-3375696 .html