前言

最近需要通过一些安卓Demo来学习熟悉部门相关业务。在配置完环境后,首先学习了Android的基本框架,了解了启动流程,并以分析了其中的init进程。也引出了系统中很多年重要的概念与机制,例如:为什么使用Binder通信机制?为什么要有硬件抽象层?为什么要设置ServiceManager? 等等,这些系统原理的细节还需要后续再深入学习。
但仅就快速学习了解Android而言,了解基本系统层面的基本架构后(系统层面初步了解),对直接交互的APP还一无所知,本文梳理里APP开发的基本信息(应用层面初步了解),后期也会对系统框架或者接口等信息进行梳理学习(系统框架层面初步了解);
在了解学习Demo之前,首先了解下Android APP的相关知识,尤其是最基本的四大组件。

图1 Android 应用主要知识

以《Android第一行代码》为例,我将App相关的基础知识分成以下几类,其中

  • 四大组件:是应用程序中最核心的元素,是应用程序与用户、系统、三方应用交互的基本模块。
  • 在基本了解四大组件的基础上,多媒体、网络、位置、数据存储以及UI布局优化等是应用开发中常用的主要功能,可以根据需求,针对性了解。
  • APP打包发布:每一个应用程序开发完成后,需要签名,生成APK (安装包),然后发布到应用市场(需要注册账号、审核,如华为应用市场),审核通过就可以下载使用,其中需要关注的除了签名+发布的流程,广告盈利也是一个重要的点,如何给APK 接入广告(如启动应用后,界面有5秒的广告-[京东-淘宝之类]),如图2所示。


图2 APK的打包发布

一、Android四大组件(为什么要学习活动+服务+广播接收器+内容提供者)

图3 Activity与Service、Boadcast Receiver 与Content Provider之间的异同

通过上图基本可以看到,Android四大组件的功能、作用,以及各自的应用场景。
首先Android的应用程序可以基本理解为一个带界面的程序,而程序可以抽象为处理数据与信息。其中:

  • 如何处理数据与信息的逻辑就编写在Activity(活动)与service(服务)中
  • UI界面的逻辑就编写在xml文件中,UI交互、反馈给用户的逻辑也在Acitivty与Service中
  • BroadCast receiver(广播接收器)与 Content Provider(内容提供器)则负责获取处理中需要的数据与信息(主要为系统、本地、应用间共享)。

如图3,我们可以简单的把四大组件分为两部分:程序(活动+服务);获取信息(广播接收+内容提供)。
在进一步介绍四大组件之前,我们可以分析下四大组件的区别,这有利于后续的学习。

  • 活动Activity与服务Service的区别是什么?
    1. 最直观的区分就是有无界面。因为需要交互,每个Acitivty包含一个UI(xml),这就比服务Service需要耗费更多的资源,当手机设备资源有限,某些设备会再资源不够的情况下优先回收一些优先级低的活动(Activity),毫无疑问,在不需要交互界面的情况下,选择服务Service更有利,
    2. 后台继续运行。这主要是二者的生命周期不同。需要强调的是,在一个应用程序(Appliction)中,可以包含多个活动(Activity)与服务Service,活动与服务都在应用程序这个进程中执行,一旦应用程序被杀死,二者也停止,因此活动与服务的主要区别就在应用程序内部。当切换活动Activity时(如切换应用,或切换浏览器不同页),当前活动就会暂停背压入栈(返回栈)中停止,但某些功能我们仍然希望能够提供,比如音乐软件被切换后,仍然能够播放音乐,浏览器软件被切换后,下载依然进行。此时能够运行于后台的服务Service就显得非常有用。
  • 广播接收器Broadcast Receiver与内容提供器 Content Provider的区别是什么?
  1. 对象与场景不同:广播接收器是允许应用接收来自各处的广播信息,而内容提供器则是主要用于跨应用程序的数据共享,因此数据对象不同。具体应用到场景上,广播接收器主要是应用接收感知系统的信息与变化,如终端的息屏亮屏,有网没网、短信等信息,而内容提供器则是主要和不同应用之间交互共享数据,如调用本地的图片(图库),或者访问其联系人等数据。
  2. 信息流通的方式不同:广播接收器如果只能接收信息,则它是单向的,无法与内容提供ContentProvicer相比,因为内容只要提供外部访问接口,那么其他应用程序都可以访问。但广播也可以发送自定义的广播,发送有两种,标准广播与有序广播,区别如图4所示。
  3. 数据类型与特点: 广播收发的数据由于很容易被其他应用获取,因此安全问题非常明显,有点类似裸奔,而内容提供器是每个应用自己选择好共享的内容,这里可以相对安全点;此外二者共享的数据体量类型也存在区别,广播由于应用环境必然属于轻量的信息,而内容提供器则共享的数据体量大、类型复杂。

广播共享数据侧重把数据信息推出去,因此如果广播发送垃圾消息,有可能影响到其他应用的安全。而内容提供则是给别人提供访问的机会

图4 标准广播与有序广播

  • 数据信息传递还有那些常用方法?
  1. Intent可完成Activity之间的通信,Intent还可以启动活动、服务、发送广播等,是活动Activity中一个重要的功能与知识点。
  2. Android中,应用中的数据属于临时数据,通过持久化可以保存到硬件存储中,某种情况下也可以通过这种方式传递信息,这种方法曾经用过,属于数据持久化,但非常不安全,在高版本中已不提倡使用。

通过学习,可以说,Android四大组件基本涵盖了一个Appliciation最重要的功能,也考虑到了各种使用环境与资源需求,这是Android应用设计者的艺术,也是快速了解Android的途径

在梳理清楚上述四大组件的特点后,接下来我们首先介绍活动Activitty与服务Service(已整理完成)再介绍广播Broadcast Receiver 和内容提供器Content Provider(未整理完成)

二、 活动Activity


图5 活动Activity的主要概念

2.1创建与注册

在使用活动前,需要先创建活动,如图6,借助AndroidStuid可以创建自己需要的模板,如空模板,基础模板等,一般IDE还会贴心的帮你创建好对应的布局文件(xml文件),并且在注册文件AndroidManifest.xml中完成活动的注册。

实际上布局文件也可以自己创建,但需要在活动中关联。可以看到,创建一个活动一般包含(UI界面xml文件+处理逻辑的活动java文件),并且需要像在头文件声明函数一样,要在注册文件中注册创建的活动文件。

UI界面是门面,包含六大布局,这个日后在学习,注册文件AndroidManifest.xml会注册很多东西,当在Activity.java文件中需要用到一些权限或者对象功能时,则需要在这个文件对应的Activity中去声明,例如申请某些权限等,其中应用MainActivity的程序入口就是一个例子。




图6 活动创建、布局设置与注册(绿框部分表明当前所属活动为程序入口,可以通过编辑修改)

2.2 常用功能

在Activity中,最常用的有Toast,用于打印信息,menu则是增加菜单。


图7-1 Toast与menu的效果


图7-2 Intent效果
Intent则是实现Activity之间的互动与通信,是最常用的功能,比如通过点击按钮,实现界面跳转。Intent通过监听按钮点击活动,处理从活动1跳转到活动2,一般在该过程中还可以携带一些信息数据,具体可以参考Intent对象。

一般点击手机back键,会自动销毁当前活动,返回上一活动,图7-2中,finish()则是通过按钮完成这一操作。

Intent的启动包含显式(指明下一个活动),隐式(不需要指明启动哪一个活动)通过指定一些列抽象的action与category信息交由系统帮忙找出合适的活动,它最大的作用是通过系统,可以启动除自己程序内的活动,还可以启动其他应用程序的活动,如打开拨号、浏览器网页等,如图7-3。

具体参考: Intent 和 Intent 过滤器 | Android 开发者 | Android Developers (google)



图7-3 Intent隐式启动拨号界面

图7-4 Intent显式与隐式启动的流程
应用程序之所以能够知道销毁当前活动,返回上时该返回哪一个活动,依靠的是返回栈(Back Stack),通过任务管理活动,当我们启动一个新的活动,它就会在返回栈中入栈,并处于栈顶每当返回或者finsh()时,就会销毁栈顶活动,出栈,上一个入栈活动重新出于栈顶。

图8 返回栈

2.3 生命周期

在上面提到的返回栈中,我们可以发现,活动存在不同的状态,栈顶的活动与用户交互,是一种运行的状态,而栈内的活动无法与用户交互,似乎处于一种停止状态,其实Android把活动的状态分为四种:

  • 运行状态:活动返回栈顶,属于系统最不太可能收回的资源。
  • 暂停状态:当活动不在栈顶,但仍处于可见状态,即当活动 没有占满屏幕的情况下,你无法与它交互,但依然可见。(目前小米华为手机上提供了在其他应用上显示的功能,不要抬杠)
  • 停止状态:活动不在栈顶,且完全不可见,系统为其保存相应状态与变量,当系统资源有限事物,会倾向于回收这些活动的资源。
  • 销毁状态:活动被从返回栈中移除,系统最倾向回收此类资源。

对应四种状态,活动包含三种生存期:

  • 完整生存期:从创建onCreate()到销毁onDestory(),在创建中完成初始化,在销毁中释放内存
  • 可见生存期:从开启onStart()到停止 onstop(),onstart是从不可见到可见时调用,onstop()是从完全不可见调用。
  • 前台生存期:从恢复onResume() 到暂停onPause(),前者表示活动恢复,准备好相应交互, 后者表示活动暂停,不接受或限制交互。

最后一种方法onRestart()是活动从停止状态(保存的变量与状态)变为运行状态前调用,即活动被重新启动,如果原有的活动被系统回收资源而销毁了,则会自动采用onCreat()创建一个新的活动,但毫无疑问,这之间需要的时间和资源肯定不一样。



具体参考Android开发手册:了解 Activity 生命周期 | Android 开发者 | Android Developers (google)

图9 Activity的声明周期

在了解生命周期后,我们继续分析返回栈,会发现存在一些问题,那就是在创建活动和返回活动时:

  1. 如果是一直打开同一个活动,那栈顶与新建活动相同若不处理直接入栈,那么返回时岂不是需要逐一返回?
  2. 如果栈内已经有一个要打开的活动了,但不在栈顶,这样不能服用,是不是有些浪费?
  3. 有一些公用活动,例如短信页面,能不能多个应用重复使用,而不仅仅是应用内使用,减少开销?

    针对这三个问题,引出了活动Activity的四种启动模式:
  • 标准模式Standard:最普通的方式,指定打开哪个活动,就打开并不做太多处理, 返回时也按照最基本的返回方式,逐步返回。

  • SingleTop:如果新建的活动与栈顶为同一个活动,则不新建入栈,否则就正常入栈。但依然可能出现栈内同一个活动重复出现的情况。
  • SingleTask:不同于singleTop,当发现栈内存在和待创建活动1一样的活动1时,直接弹出活动1上面的所有活动,直至活动1 达到栈顶。
  • Singleinstance:弃用一个新的返回栈,活动1跳到活动2(新栈,显示), 活动2跳到活动3(入栈活动1所在的返回栈,显示),返回时自然出栈,活动1变为栈顶,因此显示活动1,活动1再出栈,该栈为空,显示新栈中的活动2。

    至此,已经基本了解掌握活动的特点与生命周期,具体的开发可以参考

三、服务Service

3.1 服务创建

与活动的创建类似,选择自己需要的服务创建,创建后仅包含一个j处理逻辑的ava文件,并没有UI文件,同时AndroidStudio会自动注册创建的服务,如果需要权限,同样会在这里声明。从这一过程看,除了没有UI界面的XML文件与自身Service特点,整体与活动是一样的。


图10 创建服务

在创建与注册之后,由于服务没有接卖弄,不需要指定XML文件,同时服务不像活动可以通过Back键销毁,因此如图11所示,每个服务Service除了包含创建onCreat(),还需要启动执行onStartCommand(),以及销毁onDestory()。

其中当服务不存在时,onCreat()会执行,其内包含初始化与配置,之后每次启动服务都会仅执行onStartCommand(),其内包含响应后服务要做的事,onDestory()则是销毁。
3.2 服务启动与停止
手动调用时服务时,在创建好服务、编辑好onCreat()、onStartCommand()、onDestory()后,可以通过sartService()与stopService()来启动与关闭服务。
启动服务时,若服务不存在,则先后执行onCreat()、onStartCommand(),否则仅执行onStartCommand(); 停止服务时,则执行onDestory()。

图11

图12 服务启动与关闭

然而单纯启动后,活动与服务就没有交集了,直到停止结束服务,其中服务再干什么,有什么信息,都是没办法知道的(如下载进度等),这个时候为了实现服务与活动的通信,就需要绑定,采用绑定启动的方式,这是依靠Binder机制来实现通信的(Binder机制是Android中很重要的进程间通信方式,主要就是管理不同服务(活动也可以看成服务)之间的通信,它在学习安卓启动过程中就遇到这个名词,总之它很重要,不同服务之间通信就靠它,后续会进一步研究学习Binder)。

因此使用的就是bindService与unbinderService,相应的在启动服务时,需要在onStartCommnad(),后再多执行一步onBind(),在销毁服务前,需要在onDestory()之前多执行一步onUnbind();

3.3 生命周期

因此针对这两种服务开启情况,服务的生命周期也如下所示:

当同时使用两种方式时,必须同时调用stopService()与unbindService(), onDestory()才会执行。
服务还可以展示到前台(如通知栏的天气等),调用服务的方式也很多:

  • 通过重复调用startService 来根据意图Intent传递的参数调用
  • 通过Handle调用
  • 通过bindService调用
  • 通过AIDL调用
  • 通过BroadcastReceiver调用

四、广播接收器 Broadcast Receiver


广播特点比较简单,标准-有序的特点前面第一节已经解释过了,静态注册与动态注册的概念与区别也很好理解,重要的是动态注册一定要取消注册才能销毁。
具体接收发送,以及过滤参考: 广播概览 | Android 开发者 | Android Developers (google)

五、内容提供器 Content Rrovider

更多推荐

【Android学习】(二)四大组件