Application应用程序

第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可以是私有的,只能为它所在的应用提供数据访问请求;
  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也能穿梭于各个应用之间,把它们也联系起来。

3.1 创建Intent

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

  1. 就像给某个机构发货,只需要发送给某个机构,但不需要知道这个机构中具体是哪个人。

    //action_name可以指定那一类组件可以收到这个Intent发出的请求
    Intent i = new Intent("action_name");
  2. 就像发货时写下接收方具体的名字和地址。
    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
    {
    
        @Override
        public int describeContents() {
            return 0;
        }
    
        @Override
        public 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 {
    @Override
    public void onCreate() {
        super.onCreate();
    }
    @Override
    public void onLowMemory() {
        super.onLowMemory();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    }

    @Override
    public void onTerminate() {
        super.onTerminate();
    }

    @Override
    public 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"
        android:name=".MyApplication">      -->指定我们自定义的Application
   </application>
</manifest>

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

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

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

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

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

时间: 2024-08-26 09:04:34

Application应用程序的相关文章

WPF 10天修炼 - Application全局应用程序类

Application对象 当一个WPF应用程序启动时,首先会实例化一个全局唯一的Application对象,类似于WinForm下的Application类,用于控制整个应用程序,该类将用于追踪应用程序打开的窗口.在应用程序打开或关闭的时候能够触发相应的事件. 创建Application对象 手动创建Application应用程序对象过程: 1.  使用VS创建WPF应用程序,命名为WPFDemo.然后手动清除App.xaml文件. 2.  添加Startup.cs类,并添加程序代码.如下:

iOS程序执行顺序和UIViewController 的生命周期(整理)

说明:此文是自己的总结笔记,主要参考: iOS程序的启动执行顺序 AppDelegate 及 UIViewController 的生命周期 UIView的生命周期 言叶之庭.jpeg 一. iOS程序的启动执行顺序 程序启动顺序图 iOS启动原理图.png 具体执行流程 程序入口进入main函数,设置AppDelegate称为函数的代理 程序完成加载[AppDelegate application:didFinishLaunchingWithOptions:] 创建window窗口 程序被激活[

IOS Application生命周期

应用程序的状态 Not running(未运行):程序没启动 Inactive(未激活):程序在前台运行,不过没有接收到事件.在没有事件处理情况下程序通常停留在这个状态 Active(激活):程序在前台运行而且接收到了事件.这也是前台的一个正常的模式 Backgroud(后台):序在后台而且能执行代码,大多数程序进入这个后台后会在在这个状态上停留一会.时间到之后会进入挂起状态(Suspended).有的程序经过特殊的请求后可以长期处于Backgroud状态 Suspended(挂起):程序在后台

Android源代码之DeskClock (三) Proxy/Delegate Application 框架应用

一.概述 当项目有加壳子,插件化或热修复等需求的时候,能够使用Proxy/Delegate Application框架的方式,在正常的模式中,一个程序一般仅仅有一个Application入口,而Proxy/Delegate模式中须要有两个Application,原程序的Application改为Delegate Application,再新加一个Proxy Application,由Proxy Application 提供一系列的个性化定制,再将所有的context和context相关的引用所有

应用程序App的启动过程

应用程序App启动分两类:1. 有storyboard 2. 没有storyboard storyboard : 有storyboard情况下 1.执行 main 函数; 2.执行UIApplicationMain函数 * 创建UIApplication 对象; * 创建UIApplication 的 delegate 对象; (注: UIApplicationMain 函数的第三个参数就是 UIApplication 的名称,如果指定为 nil, 它会默认为 UIApplication, UI

**iOS开发系列--IOS程序开发概览

http://www.cnblogs.com/kenshincui/p/3890880.html 概览 终于到了真正接触IOS应用程序的时刻了,之前我们花了很多时间去讨论C语言.ObjC等知识,对于很多朋友而言开发IOS第一天就想直接看到成果,看到可以运行的IOS程序.但是这里我想强调一下,前面的知识是你日后开发IOS的基础,没有那些知识你开发IOS会很痛苦,现在很多开发人员做开发都是一知半解,程序质量确实令人担忧,所以还是希望大家能够熟练掌握前面的内容,开发过程中多思考,彻底理解程序运行的原理

UI进阶之程序启动原理及UIApplication

UIApplication对象介绍: 1> 一个UIApplication代表是一个应用程序,而且是单例的. ** 用来封装整个应用程序的一个对象, 比如当应用程序执行到某个时期要做什么, 生命周期等. 2> 获取UIApplication对象: [UIApplication sharedApplication];(单例的) /** 验证单例模式, 参考代码: - (void)viewDidLoad { [super viewDidLoad]; UIApplication *app1 = [U

iOS 应用程序生命周期

刚买了关东升老师的ios书,来记录一下自己感觉有用的东西: 作为应用程序的委托对象,Appdeletage在应用程序的生命周期的不同阶段会调用不同的方法. 首先说一下ios应用的五中状态: Not Running (非运行状态)应用程序未运行或者已经终止 Inactive (前台非活动状态)应用程序进入前台状态,但是还不能接受事件处理 Active (前台活动状态)应用程序进入前台,能接受事件 Background (后台状态)应用程序进入后台,依然能够执行代码.如果有可执行代码就会继续执行,如

计算机、程序和java概述(一)

CPU通常由两部分组成:控制器和算数/逻辑运算器 控制器用于控制和协调各个组件的工作.算术逻辑运算器用于数值运算和逻辑运算. 1MHz(兆赫) = 100万Hz 内存也称随机存储器(RAM). 操作系统的主要任务有: 控制和监视系统的活动 分配系统资源 安排操作的顺序 java application:应用程序是独立的程序,能够在任何有JVM的计算机上运行. java applet:   是一种特殊的Java程序,可以在web浏览器中直接运行. java servlet:   是一种特殊的Jav