更新时间 修改意见
2016-08-02 陈敏

第1节 应用的基本概念

我们常说的“安卓应用”可能有三种不同的概念:

  1. 软件,能够完成一个特定功能的软件。例如“安装一个应用”、“这个应用可以帮助你寻找附近的美食”。

  2. 安装包,应用的实体,是我们摸得着、看得见的APK包,是一个很具体的东西。

  3. 应用运行起来后在内存中存在的形态。安装在设备上的APK文件在系统中运行起来就是Application。Android应用开发中,常说的Application就是它。它就是Android SDK中的Application类。

在讨论程序的开发、执行、存在周期的时候,我们说的Application就是第三种意思。

第2节 Android四大组件

ActivityServiceContentProviderBroadcastReceiver被称作Android应用的四大组件,它们分别对应着一个应用程序可能用到的表现形式。

2.1 Activity

这是应用的显示组件。通常来讲,我们能看到的设备上的内容,除了状态栏(statusbar)、导航栏(navigation bar,有的安卓设备没有导航栏,用实体按键代替了)、锁屏界面,凡是显示出来的内容都属于Activity

(为了便于理解,这里讲的是大多数情况,一些窗口类型的界面–例如popupwindow,toast,输入法、壁纸等等,不应该称作Activity。)

Activity中显示的是一个应用希望呈现给用户的内容。我们开发的应用基本上一定会有一个Activity,用来向用户展示我们希望呈现的内容。例如电话拨号界面,设置界面,日历界面。

2.2 Service

这是应用可以在后台运行的服务组件,不需要有用户看得见的界面。它通常需要和Activity配合,借助Activity给用户提供控制的界面。

最典型的例子就是音乐播放器。音乐播放器的界面就是一个提供了音乐控制方式的Activity,当我们点击Activity上的播放按钮之后,Activity通知播放器的Service组件,让Service组件开始播放音乐;之后即使用户选择退出了音乐播放器的Activity界面,音乐仍然在被播放着,没有随着界面的退出而停止播放。

2.3 ContentProvider

这是一个应用的数据存储组件。在Android系统中,出于数据安全的考虑,应用之间是被严格的隔离的,应用A不能访问到应用B的数据。但是如果应用B使用了ContentProvider组件,就能让应用A通过Android系统制定好的规则获取到应用B愿意提供的数据了。

它就像是一个拥有某种数据的网站,安卓系统运行的其它组件可以通过“网址”访问这个网站,获取需要查询的数据。

  1. ContentProvider可以是私有的,只能为它所在的应用或具有相同ShareUserId的应用提供数据访问请求;
  2. ContentProvider也可以是公开的,能为别的应用程序提供数据访问请求。

2.4 BroadcastReceiver

这是应用获取系统或者获取某些应用发出特定消息的组件。

例如,有个应用叫“换壁纸”,它希望设备开机完成后,自动更换桌面壁纸。可是开机后“换壁纸”还没有运行起来,用户也不会主动的告诉“换壁纸”“手机已经启动了,换一张壁纸吧”。

这时,就可以通过BroadcastReceiver组件获取开机完成后系统主动发出的“开机完成通知”。得到“通知”后,“换壁纸”就可以按照预想设计工作了。

BroadcastReceiver组件有个特点,就是包含它的应用不一定要正在运行,系统可以根据“通知”类型,先把这个“通知”告诉关注它的BroadcastReceiver,由BroadcastReceiver决定是否需要启动一个Activiy或者Service来做相应的处理。

第3节 Intent初步

如果将ActivityServiceBroadcastReceiver这些组件比喻成一座一座的岛屿,那么Intent就是穿梭于这些小岛之间的小船。

  • 从主界面启动Activity,需要通过Intent;
  • 在Activity里面启动另一个Activity,也需要通过Intent;
  • 启动Service需要通过Intent;
  • BroadcastReceiver被唤醒,也是通过Intent。

Intent不仅能将这些组件联系了起来。Intent也能穿梭于各个应用之间,把它们也联系起来。

Activity, Service 和 BroadcastReceiver之间可以通过Intent互相启动。

3.1 创建Intent

在创建Intent的时候,可以使用下面的方式指定小船的目的地。

  1. 给某个机构发货,只需要发送给某个机构,但不需要知道这个机构中具体是哪个人。这叫做隐式Intent

    //action_name可以指定哪一类组件可以收到这个Intent发出的请求
    Intent i = new Intent("action_name");
  2. 给指定的个人发货,写下接收方具体的名字和地址。这叫做显式Intent

    Intent i = new Intent();
    i.setClassName("接收方的包名", "接收方的类名"); 

3.2 携带数据

小船可以携带货物,Intent也可以携带各种类型的数据。在创建Intent对象后,使用如下的方法,你就可以把想要在“岛屿”之间传递的数据放到小船上。

Intent i = new Intent();
i.putExtra("索引关键字",goods);

这些数据包括Stringcharlongintbooleanfloatdoublebyte等等常用的基本类型,也包括它们的数组。甚至还能传递自定义类封装的对象。

不过要传递自定义类封装的对象,需要这个类做特殊的处理,

  • 继承了Serializable接口,

    class data implements Serializable
    {}Intent i = new Intent();
    i.putExtra("DATA", new data());
  • 继承了Parcelable接口,

    class data implements Parcelable
    {@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {}
    }Intent i = new Intent();
    i.putExtra("DATA", new data());

Parcelable的性能要比Serializable好很多,传输的效率要高上10倍左右;但是Parcelable需要开发者自己定义数据序列化和反序列化的规则,所以编码量比使用Serializable要大很多。

在实际的开发场景中要根据实际的情况作选择。

第4节 Manifest初步

在应用工程的源码目录下,都有一个AndroidManifest.xml文件,它是这个应用的配置文件,当应用安装到设备上后,Android系统会从这个文件中获取很多关于这个应用的配置信息。

Manifest文件内容,大体如下:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.anddle.activitytest"><uses-permission /><permission /><permission-tree /><permission-group /><instrumentation /><uses-sdk /><uses-configuration />  <uses-feature />  <supports-screens />  <compatible-screens />  <supports-gl-texture />  <application
        android:icon="@mipmap/ic_launcher"android:name=".MyApplication"><activity android:name=".MainActivity"/><service android:name=".MyService"/><provider android:name=".MyContentProvider"android:authorities="com.anddle.authoriteies"/><receiver android:name=".MyReceiver"/></application>
</manifest>

不是所有的项都需要在Manifest文件中使用,通常只会用到最常用的。

4.1 application标签

应用使用了哪些组件,都要在这个配置文件中登记。不然在程序启动这些组件的时候,系统会找不到它们,导致程序崩溃。

<application
   android:icon="@mipmap/ic_launcher"android:name=".MyApplication"><activity android:name=".MainActivity"/><service android:name=".MyService"/><provider android:name=".MyContentProvider"android:authorities="com.anddle.authoriteies"/><receiver android:name=".MyReceiver"/></application>

4.2 uses-permission标签

这个应用要使用系统的哪些权限,也要在这个配置文件中声明。这样在安装的时候,系统会根据填写的内容,告诉用户,让用户判断是否接受应用使用这些系统的功能。

例如,一个应用要读取磁盘存储器上的内容,就需要申请权限,如果用户同意,才能成功读取磁盘。

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

第5节 Task、Application与四大组件的关系

5.1 Task

在Android系统中,很多模块是互用的。例如当我们启动“相机”拍摄了一张照片,然后通过“图库”浏览刚拍的照片,最后选择“微信”将照片分享出去。为了实现这一些列的操作,达到我们希望的目的,整个过程就利用了3个不同应用,分别使用了它们对应的Activity。

我们将使用到的这些Activity串在一起,称作Task。它们就像一个叠叠乐,后启动的放在另一个的上面–我们给这个叠叠乐一个专业的术语–栈。Task中包含的Activity是以栈的形式存放的。

假如此时,我们按返回按钮一步一步返回,Task中位于顶部的Activity就被一步一步退出,直到退出这个Task中所有的Activity,然后回到了系统主界面。

假如此时,我们按home按钮,就会返回到系统主界面,同时将这个Task保存下来。如果你再启动主界面上的另一个应用,一个新的Task就会被建立起来。

通过上面的描述,我们可以知道:Task只和Activity有关。

另外,Task可以在系统中存在多个,例如启动应用A,创建Activity A,这里就有一个Task A了;然后按“home”键返回,再启动应用B,创建Activity B,这里就有一个Task B了;以此类推,会有Task C Task D。

不过运行在最前台的只有一个Task,这就是前台Task。其他的Task都是后台Task。

5.2 Application与组件的关系

站在系统的角度看,Application就是运行着组件的进程环境。这个进程环境中运行着正在工作的组件---即那些在它Manifest中声明了的、正运行着的组件。以上面微信分享照片的task作为例子。

相机应用:虽然没有被看见,但它还有Activity存在着,它运行的线程环境还存在着,所以这个application正在运行着;

图片浏览应用:虽然没有被看见,但它还有Activity存在着,它运行的线程环境还存在着,所以这个application正在运行着;

微信应用:很明显,它有Activity运行着,它运行的线程环境存在,所以这个application正在运行着;可以想象微信一定有个正在后台接受网络发送了消息的Service 。这个Service也是application的一部分--因为他们在同一个线程当中(这种说法并不严谨,如果Service被指定了在单独的进程中运行,那么application就不是同一个了。不过这里为了举一个贴近实际场景的例子,就没有去做详细的区分了);

Application可以看做是这些组件的集合,是这些组件对外共同的名字。

Application被运行起来的情况有:

  1. Activity被启动,显示出一个界面;
  2. service被启动,在后台默默的运行;
  3. 其他应用开始访问自己提供的ContentProvider;
  4. BroadcastReceiver收到了一个“消息”;

站在系统的角度看,当应用运行起来时,系统为这个应用创造了一个线程环境,这个线程环境就是Application,那些组件运行的环境都在这个线程当中。

由此可知,Application是一个安装应用的入口。不过通常来讲,在通过Android Studio创建工程的时候,并没有给我们指出这个Application,而是使用了系统默认的Application。

另外Android Studio还为我们创建了一个Activity。这多少会让我们误以为Activity才是应用程序被最早启动的地方。

要自己定义应用的Application环境,首先要在代码中继承Application类。这里列出了一部分可以被覆盖的Application类方法。

public class MyApplication extends Application {@Overridepublic void onCreate() {super.onCreate();}@Overridepublic void onLowMemory() {super.onLowMemory();}@Overridepublic void onConfigurationChanged(Configuration newConfig) {super.onConfigurationChanged(newConfig);}@Overridepublic void onTerminate() {super.onTerminate();}@Overridepublic void onTrimMemory(int level) {super.onTrimMemory(level);}
}

这里的onCreate()函数才是一个应用被启动的第一个地方(而非Activity的onCreate())。

创建Application类后,我们要在manifest文件中,指明我们的应用使用这个自定义的Application:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.anddle.activitytest">......   <application
        android:icon="@mipmap/ic_launcher"<!--指定我们自定义的Application-->android:name=".MyApplication">......</application>
</manifest>

如果这里不指定android:name,那么系统将使用默认的Application。

不是所有的应用都需要使用自定义的Application,对于那些有很多组件(Activity Service等等)都需要做相同初始化的应用,就可以使用它。

例如,有个应用包含一个Activity和一个Service,无论是哪个先启动,都首先要去做一个共同的操作。这种情况就可以考虑把那个共同的操作放到Application中进行。

Application还可以作为各个组件共享变量和数据的仓库。

Activity和Service都是有生命周期的,一旦生命结束,它们保存的一些数据就会被释放掉。但是它们的生命结束了,不代表Application的生命结束了(Application是整个应用的生命)。为了其他组件还能继续使用这些数据,我们就可以把数据放在这个生命更长的Application中。


/*******************************************************************/
* 版权声明
* 本教程只在CSDN和安豆网发布,其他网站出现本教程均属侵权。

*另外,我们还推出了Arduino智能硬件相关的教程,您可以在我们的网店跟我学Arduino编程中购买相关硬件。同时也感谢大家对我们这些码农的支持。

*最后再次感谢各位读者对安豆的支持,谢谢:)
/*******************************************************************/

Application应用程序相关推荐

  1. 《UnityAPI.Application应用程序》(Unity+SteamVR+云技术+5G+AI+VR云游戏+API+dataPath+OpenURL+LoadLevel+立钻哥哥++OK++)

    <UnityAPI.Application应用程序> 版本 作者 参与者 完成日期 备注 UnityAPI_Application_V01_1.0 严立钻 2020.05.12 #< ...

  2. WPF教程(二)--Application WPF程序启动方式

    1.Application介绍 WPF与WinForm一样有一个 Application对象来进行一些全局的行为和操作,并且每个 Domain (应用程序域)中仅且只有一个 Application 实 ...

  3. web项目怎么打包上线_如何打包发布Web Application应用程序

    最近做了一个网站,结果发布的时候发现自己建的是Web Application,如何打包发布Website,想必大家都很熟悉,查了点资料,发现都是英文的很多,现在自己整理给大家,希望对大家有帮助. 任务 ...

  4. java程序可以分为应用程序和,Java程序的可以分为Application应用程序和__________ 答案:Applet小应用程序...

    可以带绝缘柄之电工钳湿木柄之斧等类具断电源线也:× 病人诊为痈也,最可见下何项血常规也:性细胞明显增粒 Heaskedusto _ _ _ _ _ _ _ _themincarryingthrough ...

  5. CDR插件开发之Application(应用程序)

    在CorelDRAW提供的对象模型中,Application是被开发者经常使用的一个对象,也是最顶级的对象.本文对CorelDRAW(以下简称CDR)对象模型中的 Application 类做了一个简 ...

  6. iOS应用程序生命周期(前后台切换,应用的各种状态)详解

    2019独角兽企业重金招聘Python工程师标准>>> iOS的应用程序的生命周期,还有程序是运行在前台还是后台,应用程序各个状态的变换,这些对于开发者来说都是很重要的. iOS系统 ...

  7. [转]孙鑫VC教程例子代码1---Windows程序内部运行原理

    本文转自:http://blog.csdn.net/ljt350740378/article/details/6437113 创建一个完整的窗口需要经过下面四个操作步骤: 设计一个窗口类: 注册窗口类 ...

  8. IOS开发系列--IOS程序开发概览

    IOS开发系列--IOS程序开发概览 2014-08-04 19:42 by KenshinCui, 9983 阅读, 51 评论, 收藏, 编辑 概览 终于到了真正接触IOS应用程序的时刻了,之前我 ...

  9. java 线程崩溃_java语言中application异常退出和线程异常崩溃的捕获方法,并且在捕获的钩子方法中进行异常处理...

    1.application应用程序注入自定义钩子程序 java语言本身提供一个很好的Runtime类,可以使我们很好的获取运行时信息.其中有一个方法是 public void addShutdownH ...

最新文章

  1. 【Linux实用技术】LFS6.3构建实录
  2. Apache POI和EasyExcel 第四集:Apache POI的Excel基本读取(分为03版的xls、07版的xlsx)
  3. 如果《赛博朋克2077》走进现实,人类如何摆脱AI的支配?
  4. 禁掉人脸识别!一群音乐人正在号召,禁止在音乐节上动用人脸识别
  5. 左神算法:将单链表的每K个节点之间逆序(Java版)
  6. 微前端概述(Micro Frontends) 以及相比单体应用,微前端能带来什么好处
  7. antlr4例子_ANTLR和网络:一个简单的例子
  8. js实现冒泡排序,快速排序,选择排序
  9. list 泛型_带你深挖Java泛型类型擦除以及类型擦除带来的问题
  10. EBS AP 创建会计科目失败
  11. STM32F407+Cubemx学习应用[5]——DMA收发ModbusRS232数据——威纶通触摸屏
  12. java左手画圆右手画方_左手画圆右手画方可以同时进行吗?
  13. 总价合同、成本补偿合同、工料合同
  14. 手机端Alook浏览器手动抓取京东Cookie教程
  15. 量化系统工程师需要学什么?
  16. Oracle 时间差计算
  17. C语言学习笔记 | 进阶 | 文件操作详解(万字精心制作)
  18. 2020Cfa最新mock下载和使用
  19. 浅谈网络之“TCP协议”
  20. 关于计算机的名言英语作文,适用于英语作文的名人名言

热门文章

  1. php distinct 用法,distinct的用法
  2. 出差忘带电脑脑袋炸裂?鼓捣了下个人云,真香
  3. 工作簿(Workbook)基本操作应用示例(一)
  4. [培训-无线通信基础-0]:课程概述
  5. 红外成像单筒望远镜TFN TD7产品 型号评测
  6. C++ typedef typename 作用
  7. 图解快速排序——通俗易懂(quick sort)
  8. 图像的超分辨率重建SRGAN与ESRGAN
  9. 【机器学习算法】神经网络和深度学习-4 重要的BP网络使用总结,了解BP神经网络的魅力
  10. SecureCRT常用的几个命令