1.android框架、android系统启动过程、binder框架、软件开发架构、消息驱动模型
2.Activity、Service、ContentProvider、BraodcastReceiver和Intent
四大组件的使用都必须要在AndroidManifest.xml配置文件中声明,否则系统将不识别也不执行该组件。
1)活动Activity
(1)对Activity的理解: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)。
(2)Activity是一个组件,一个活动就是一个屏幕,它负责创建窗口容纳视图组件。每个活动都继承活动基类被实现为一个独立的类。活动类可以显示由多个视图空间组成的用户接口,并对事件做出响应。一个activity中通常包含多个widget,一个intent,一个布局(xml或Java代码实现),一个bundle。
(3)Activity的生命周期:
(4)Activity的启动与停止:
2)服务service
服务在后台运行,没有界面,相当于activity启动的守护进程。可以被activity产生或激活,处理与当前activity生存期无关的事务。服务用于在后台完户指定的操作。
(1)从启动和停止方式的角度,service分为以下2种
(a)starte型:当应用程序组件(如activity)调用startService()方法启动服务时,服务处于started状态。该service的生命周期由自己决定。started service(启动服务)是由其他组件调用startService()方法启动的,这导致服务的onStartCommand()方法被调用。当服务是started状态时,其生命周期与启动它的组件无关,并且可以在后台无限期运行,即使启动服务的组件已经被销毁。因此,服务需要在完成任务后调用stopSelf()方法停止,或者由其他组件调用stopService()方法终止服务。
(b)bind型:当应用程序组件调用bindService()方法绑定到服务时,服务处于bound状态。使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦调用退出该activity,服务也就终止。该service的生命周期与当前组件的生命周期相同。调用者也可以使用unbindservice()解除绑定终止service。
(2)从作用范围的角度,service类型分为以下2种
(1)本地服务:用于应用内部,实现应用程序自己的一些耗时任务。
(2)远程服务:用于应用程序之间,允许调用其他应用程序的服务。
service类派生了多种类型的服务:AbstractInputService AccessibilityService IntentService RecognitionService WallpaperService
(3)Service的2个应用
*作为应用程序的一种设施,以一种与当前activity无关的方式启动一段Java代码。通过context.startService方法启动Service,或通过context.stopService终止。
*在应用程序之间提供交互功能:通过调用context.bindService方法启动一个长期的Service。调用context.unbindService终止
(4)服务的生命周期
(4)Service的实现过程
*创建Service:首先需要继承Service类,并且覆盖其中的onCreate,onStart, onDestroy方法
*onCreate 中实现需要在后台执行的代码
*onStart intent数据通常都是传递给onstart
*onDestroy 实现清除数据
(5)Service的启动与终止
3)BroadcastReceiver的实现方法
(1)对广播的理解
BroadcastReceiver可以对外部事件进行过滤,只对感兴趣的外部事件(如当电话呼入时,或者数据网络可用时)进行接收并做出响应。它们可以启动一个activity或serice来响应它们收到的信息,或者用NotificationManager来通知用户。通知可以用很多种方式来吸引用户的注意力,例如闪动背灯、震动、播放声音等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息;广播接收者的注册有两种方法,分别是程序动态注册和AndroidManifest文件中进行静态注册;动态注册广播接收器特点是当用来注册的Activity关掉后,广播也就失效了。静态注册无需担忧广播接收器是否被关闭,只要设备是开启状态,广播接收器也是打开着的。也就是说哪怕app本身未启动,该app订阅的广播在触发时也会对它起作用。
Broadcastreceive组件:继承broadcastreceive类,实现onReceive()方法,提供了一种更加自由的使用intent和notification的方式,是intent的消费者并根据intent激发其它组件。Broadcastreceive生命周期只有十秒左右,如果在onReceive()内做超过十秒内的事情,就会报ANR(Application No Response) 程序无响应的错误信息,如果需要完成一项比较耗时的工作 , 应该通过发送 Intent 给 Service, 由Service 来完成。
(2)广播接收器分为2种:与activity绑定的广播接收器和作为独立组件的广播接收器。
(3)广播的启动和停止
4)内容提供器ContentProvider
ContentProvider提供了一种多应用间数据共享的机制以及数据存取的标准接口。Content Provider使一个应用程序的指定数据集提供给其他应用程序。其他应用可以通过ContentResolver类从该内容提供者中获取或存入数据;当在多个应用程序间共享数据时才需要内容提供者。例如,通讯录数据被多个应用程序使用,且必须存储在一个内容提供者中。它的好处是统一数据访问方式;ContentProvider实现数据共享。ContentProvider用于保存和获取数据,并使其对所有应用程序可见。这是不同应用程序间共享数据的唯一方式,因为android没有提供所有应用共同访问的公共存储区;开发人员不会直接使用ContentProvider类的对象,大多数是通过ContentResolver对象实现对ContentProvider的操作;ContentProvider使用URI来唯一标识其数据集,这里的URI以content://作为前缀,表示该数据由ContentProvider来管理。
5)意图intent
intent是一种运行时绑定机制, 是一种利用消息进行交互的机制。与intent有关的2个类是IntentFilter和IntentReceiver。Intent提供应用程序、activity和service三种之间的相互触发和数据交互(运行时绑定)。intent描述了一次操作的动作、动作涉及的数据和附加数据,intent用于通知系统内核调用intent指定的应用。intent分成2类:(1)显式intent:显式intent直接指定需要启动的组件的名字来启动activity、service或BroadcastReceiver。(2)隐式intent:隐式intent无需指定目标应用的名字,只需选择性的指定Intent的Action、Data以或Category,则具有过滤这些Intent的4大组件就能被这些Intent激活。4大组件中Activity、BroadCastreceiver、service这3个都是通过intent被激活的。
Android的核心Intent:连接4大组件的纽带Intent是一种利用消息进行交互的机制。Intent对象描述了应用中一次操作的动作、涉及的数据和附加数据,FrameWork通过Intent的描述调用对应的用户的应用、底层应用、service、activity或BroadcastReceiver。Intent提供了组件之间的延迟绑定机制。通过Intent调用底层应用必须设置底层应用许可。
意图用于激活各个组件及各个组件之间通信,可以携带数据。
3.资源管理器Res/Assets
*在activity类中 Resource resmanage=this.getBaseContext().getResources(); Drawable pic1=resmanage.getDrawable(R.id.pic1); 可以获取到该图片资源的引用
通过Android应用程序资源的编译和打包过程,最终得到的应用程序资源就与应用程序代码一起打包在一个APK文件中。Android应用程序在运行的过程中,是通过一个称为AssetManager的资源管理器来读取打包在APK文件里面的资源文件的。
访问app内部的资源:应用程序的每一个Activity组件都关联有一个ContextImpl对象,这个ContextImpl对象就是用来描述Activity组件的运行上下文环境的。Activity组件是从Context类继承下来的,而ContextImpl同样是从Context类继承下来的。在Activity组件调用的大部分成员函数都是转发给与它所关联的一个ContextImpl对象的对应的成员函数来处理的,其中就包括用来访问应用程序资源的两个成员函数getResources和getAssets。ContextImpl类的成员函数getResources返回的是一个Resources对象,有了这个Resources对象,就可以通过资源ID来访问那些被编译过的应用程序资源。ContextImpl类的成员函数getAssets返回的是一个AssetManager对象,有了这个AssetManager对象,就可以通过文件名来访问那些被编译过或者没有被编译过的应用程序资源文件。
Resources类的实现:事实上,Resources类也是通过AssetManager类来访问那些被编译过的应用程序资源文件的,不过在访问之前,它会先根据资源ID查找得到对应的资源文件名。在Android系统中,一个进程是可以同时加载多个应用程序的,也就是可以同时加载多个APK文件。每一个APK文件在进程中都对应有一个全局的Resourses对象以及一个全局的AssetManager对象。其中,这个全局的Resourses对象保存在一个对应的ContextImpl对象的成员变量mResources中,而这个全局的AssetManager对象保存在这个全局的Resourses对象的成员变量mAssets中。Resources类有一个成员函数getAssets,通过它就可以获得保存在Resources类的成员变量mAssets中的AssetManager,例如,ContextImpl类的成员函数getAssets就是通过调用其成员变量mResources所指向的一个Resources对象的成员函数getAssets来获得一个可以用来访问应用程序的非编译资源文件的AssetManager。
访问系统资源:Android应用程序除了要访问自己的资源之外,还需要访问系统的资源。系统的资源打包在/system/framework/framework-res.apk文件中,它在应用程序进程中是通过一个单独的Resources对象和一个单独的AssetManager对象来管理的。这个单独的Resources对象就保存在Resources类的静态成员变量mSystem中,我们可以通过Resources类的静态成员函数getSystem就可以获得这个Resources对象,而这个单独的AssetManager对象就保存在AssetManager类的静态成员变量sSystem中,可以通过AssetManager类的静态成员函数getSystem同样可以获得这个AssetManager对象。访问该assets文件中的资源可以使用“file:///android_asset/...”
4.Bundle类
Bundle类型,相当于map,用于activity之间的数据传递。传递的数据可以是boolean、byte、int、long、float、double、string等基本类型或它们对应的数组,也可以是对象或对象数组。当Bundle传递的是对象或对象数组时,必须实现Serializable 或Parcelable接口。
5. View视图类和Widget类及其事件监听器类
*View类是所有Widget类以及所有监听器类的基类
*Widget主要包括以下视图:TextView文本框视图 EditText编辑框视图 Button CheckBox复选框视图 RadioGroup Spinner下拉列表 AutoCompleteTextView自动完成文本框视图 DatePicker日期选择器视图 TimePicker时间选择器视图 DigitalClock数字时钟 AnalogClock表状时钟 ProcessBar进度条 RatingBar评分条 SeekBar拖动条 GridView网格视图 ListView列表视图 ScrollView滚动视图 ImageView图片视图 Tab图标切换视图
*TextView和ImageView的区别就是-TextView用于显示文本而ImageView用于显示图片 ContextMenu菜单 OptionsMenu
*每一种视图都有自己的事件监听器,当事件到来时将触发回调函数。
*菜单结构的设计有2种:Java代码和XML。首先进行UI设计,通过@+id/xxx为组件对应一个对象关键字。UI设计完之后,就产生了每个组件对应的对象,但是在代码里还无法引用该对象,因为没有这些widget对象的引用,使用findViewById(R.id.xxx)可以返回这些已布局对象的引用。
*键盘事件属于activity的事件,可以通过覆盖onKeyUp()或onKeyDown()方法捕获按键值
6.Android的通知:Notification和Toast
Notification:被用来通知用户某个事件发生了,比如短信短信,显示在当前activity的状态栏中。该通知方式可以绑定一个intent,当该通知被点击时,将发送该intent。Notification允许设置标题,这样可以在“通知窗口”中浏览通知列表,当用户点击某个通知时,Notification设置的Intent就会触发。
所以的Notification被NotificationManager系统服务管理,通过getSystemService(context.NOTIFICATION_SERVICE)获得NotificationManager对象,然后调用notify方法将Notification对象传递给用户。
NotificationManager nm=(NotificationManager)this.getsystemservice(NOTIFICATION_SERVICE);
PendingIntent myintent=PendingIntent.getActivity(this,0,new Intent(this,Ex_81.class),0);/*生成通知的PendingIntent对象*/
Notification notifi=new Notification(drawable/*图片*/,tickertext/*标题*/,system.currenttimemillis()/*发送时间*/);
notifi.setLatestEventInfo(this,title,content,myIntent);
nm.notify(R.layout.activy_notification,notifi);
/*删除一个状态栏中的通知*/
nm.cannel(R.layout.activy_notification);
Toast:悬浮于屏幕上,但不会获得焦点。不能够绑定事件。
调用方法简单:直接使用静态函数Toast.maketext(this,"...",Toast.LENGTH_LONG)
7.Android提供了4种持久数据存储的方法
*Preferences存储数据:Preferences采用"键-值"对组织和管理数据,其数据存储在XML文件中,适用于简单数据存储。可以像bundle存取数据
*文件存储数据:从存储量来看,文件存储是一种"重量级"的存储机制,它比Preferences方式更适合存储较大的数据。
*SQLite存储数据:“重量级“存储机制
*ContentProvider存储数据(非持久):应用程序之间唯一共享数据的途径,主要用于存储、检索数据以及向其他应用程序提供数据访问的接口。可以提供像sqlite一样的数据访问方式,可以存储非结构化数据。
8. android提供了3种网络通信方式
*Webkit(android.webkit):浏览器引擎
*HttpComponents
*Socket(java.net.*)
9、杂项
(1) 所有的Android 应用进程都是由Zygote fork出来的。
(2) 组件管理:zygote进程->systemservice进程->AMS系统服务进程(activity manage service)--binder->四大组件
(3) App本质上是组件和资源的容器
(4) Context实现组件进程间的环境切换,activity和service以及application都是context的子类,允许他们直接从当前进程切换到下一个进程。
本文出自 “tech记录” 博客,谢绝转载!