分类目录归档:大话Android应用开发

四大组件之Activity 第7节 ADB工具调试Activity

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

第7节 ADB工具调试Activity

为了帮助我们深入学习Activity,这里介绍通过ADB工具获取系统中现有Activity信息的方法。

7.1 打印系统Activity信息

用命令行工具进入adb所在的目录,
输入adb shell dumpsys activity activities,会输出类似如下的内容:

它记录下了当前安卓系统中所有的Task,以及每个Task中包含的Activity信息。

例如这里记录了,

  1. 系统中有一个Task id#178Task;
  2. Task栈中的Activity,从上到下依次是TaskRecord---com.android.launcher3/.Launcher,一个Activity
  3. 并且com.android.launcher3/.Launcher这个Activity是位于前台的Activity

这些信息对程序的调试会有很大的帮助。

7.2 ADB启动Activity

用ADB工具启动已知Activity,

这里的包名就形如:com.android.launcher3,例如


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

四大组件之Activity 第6节 Activity启动模式

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

第6节 Activity启动模式

Activity的启动模式,就是指当用户或者系统启动一个Activity时,将这个Activity如何放到Task中进行管理。

Activity有四种启动方式:standard、singleTop、singleTask、singleInstance。

6.1 standard模式

这是每个Activity默认的启动模式,如果我们没有在manifest中指定,那么Activity启动就会采用这个模式。这个模式很简单,原则只有一个:当启动这种类型的Activity时,每次创建一个全新的Activity,然后将它放在当前Task栈的栈顶。

进一步举个例子:Activity A上,有一个按钮,点击后,可以再启动一个Activity A。这时我们看到的Task堆栈情况就是,Activity A上又创建了一个Activity A。这两个Activity都是Activity A的实例,是互相独立的Activity,在内存中有各自的一块区域。

6.2 singleTop模式

这个启动模式的原则是:当启动这个类型的Activity时,如果这个Activity有实例在当前Task中存在,并且位于这个Task的栈顶,那么就触发Activity的onNewIntent()方法通知一下,而不用重新创建;

否则,即使这个Task中有这个Activity实例,只要它不在栈顶,就重新创建;


使用场景:一个新闻客户端会接收新闻推送,在statusbar上显示已经收到10条推送了。当我们点击第一条的时候,启动一个显示新闻内容的Activity-ContentActivity,当我们点击statusbar上的第二条新闻时,再次启动ContentActivity。如果ContentActivity是standard模式,可以想见,在之前的新闻内容上,又回弹出一个Activity,10条推送点击十次,就会有10个Activity叠在一起。

麻烦的是返回时得按10次,而且会占用很多系统资源。

如果将ContentActivity指定为singleTop,那么点击后面9条推送时,ContentActivity只会通过onNewIntent()知道有新的调用请求,不必重新创建9个Activity实例过份消耗资源。

6.3 singleTask模式

这个启动模式的原则是:当启动这个类型的Activity时,先查看这个Activity是否有实例在系统当前的Task中存在。

6.3.1 前台Task中存在

如果它在位于前台的task中存在,并且位于这个Task的栈顶,那么就调用onNewIntent()通知一下,而不用重新创建--这一点与singleTop模式类似;

如果存在,但是不在Task的栈顶,就将这个Activity上面别的Activity全部弹出、销毁,把这个Activity的实例放到最上面,再用onNewIntent()通知它一次。

6.3.2 后台Task中存在

如果它在位于后台的task中存在,就把后台task放到前台来,然后把它上面存在的别的Activity弹出、销毁。


使用场景:应用的主Activity A,可以启动Activity B, Activity B又能启动Activity C,C又能启动D,设计者希望从D能够直接返回到主Activity A。

对于这种希望在任意层级的Activity下,快速返回到主界面的应用,就可以把主Activity A设置成singleTask模式。

6.4 singleInstance模式

这个启动模式的原则是:当启动这个类型的Activity时,如果该Activity之前并不存在,就会重新创建一个Task,并把该Activity放入其中。假如这个Activity要启动别的Activity-C(一个standard的Activity),那么就会将Activity-C放在之前那个Task中。

如果该Activity已经存在,就把该Activity所在的task切换到前台来。
总之,一个task中有且只有一个这种类型的Activity。


使用场景:对于那种需要提供给第三方调用的Activity,例如微信的分享、转发,就可以把这种Activity设置成singgleInstance。这样在系统范围内保证只有一个这样的Activity存在。


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

四大组件之Activity 第5节 Activity的Manifest配置

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

第5节 Activity的Manifest配置

Actiity需要在AndroidManifest.xml文件中进行声明。

5.1 Activity的声明

Activity作为四大组件,代码中每定义一个Activity就需要在AndroidManifest.xml文件中声明它。

5.2 Activity标签常用属性

Activity标签还有一些我们常用到的属性。

  1. 这里的intent-filter标签内指定的内容表示:这个Activity可以作为这个应用程序的入口。

    直观一点,就是说它可以被放在桌面上,供用户通过点击直接进入。假如一个应用有三个这种intent-filter配置的Activity,那么桌面上将有三个图标,供用户点击启动。

  2. 指定Activity的主题。安卓系统为界面元素设计了几种不同的显示风格,叫做主题。关于主题的详细介绍我们将放在以后的章节。

  3. 指定Activity的启动方式。启动方式在下一小节详细讲述。

  4. 指定Activity是否关注系统配置的变化,如果关注,当这些配置发生变化的时候,将通过Activity的onConfigurationChanged()函数通知到。

  5. 响应特定的Action,遇到这样的Action就可以启动该Activity,

    那么,启动该Activity的代码,就可以通过它配置中的Action

除了以上列出的一些属性外,Activity的很多特性都可以这样设置。


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

四大组件之Activity 第4节 系统设置改变onConfigurationChanged

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

第4节 系统设置改变onConfigurationChanged

当设备的系统设置发生变化时,例如横竖屏切换、语言变化,可以被Activity感知到。

4.1 监听系统设置改变

系统设置发生变化可以通知到Activity,

  1. AndroidManifest.xml文件当中,给对应的Activity标签,添加android:configChanges属性,例如

  2. 在需要在实现Activity的代码中做出相应的修改:

在manifest中指定关注的是screenSizeorientation,那么当手机从横屏变化成竖屏(或者竖屏变化成横屏)的时候,这个函数就会被调用,就可以在这里添加我们需要的代码。

系统变化的种类很多,除了screenSizeorientation还有:keyboardHidden locale fontScale等等。

4.2 设备旋转

我们可以用两种方法处理设备的旋转,

  1. 让Activity不跟随设备方向的旋转而旋转,它只有竖屏(或只有横屏)的界面。要做到这一点很容易,在AndroidManifest.xml文件中,给这个Activity组件加上android:screenOrientation="portrait"
    (保持竖屏)或者android:screenOrientation="landscape"(保持横屏)的属性就可以了;

  2. 让Activity跟随设备方向的旋转而旋转。
    采用章节3.2中介绍的方法。


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

四大组件之Activity 第3节 Activity的系统回收

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

第3节 Activity的系统回收

在Activity生命的周期中,安卓系统可能直接回收Activity。系统回收Activity有两种常见的情况,

  1. 系统资源紧张;
  2. 屏幕的旋转;

3.1 资源紧张

当系统资源紧张时,例如你打开了很多应用,系统中的可用内存很少了。这时安卓系统会采用一定的策略来回收系统中的资源,这些资源包括前台可见的Activity、后台不可见的Activity,后台中运行的Service,在状态栏中给出了“正在运行”的提示的Service等等。

在回收资源的时候,系统会根据这些资源所在的进程优先级来判断。进程优先级高的,最后回收;进程优先级低的,最先回收。 这些进程优先级从高到低分别是,

  • 前台优先级-IMPORTANCE_FOREGROUND,它可能是,

    • 一个正在与用户进行交互的Activity;

    • 一个被Activity绑定的Service,而这个Activity正在与用户进行交互;

    • 一个被调用了startForground()方法的Service,此时它的优先级被设置成了前台优先级;

    • 一个正在经历周期变化的Service(也就是说这个Service的onCreate() onDestroy()等周期变化的方法正在被触发调用);

    • 一个正在执行onReceive()BroadcastReceiver

  • 可见优先级-IMPORTANCE_VISIBLE,它可能是,

    • 一个虽然用户不能交互、但是用户仍然能看到的Activity;

    • 一个绑定了可见Activity的Service;

  • 服务优先级-IMPORTANCE_SERVICE,它可能是,

    • 一个普通的Service(没有处于前台优先级和可见优先级中那些Service的状态);
  • 后台优先级-IMPORTANCE_BACKGROUND,它可能是,

    • 不可见的Activity;
  • 空优先级-IMPORTANCE_EMPTY,

    • 它当中没有任何应用组件,它只是为了提高应用的启动速度而预留的空进程,可以随时被系统回收。

这里举个例子,资源极度匮乏的时候,

  1. 系统会优先回收那些没有显示的Activity(例如在onStop()状态下的Activity);
  2. 如果回收那些资源以后,发现资源还是不够用,就会回收虽然显示了、但却没有和用户做交互的Activity(例如在onPause()状态下的)。

这里会遇到一个问题:假如Activity A启动了Activity B之后,系统发现内存不足,在回收了其它所有资源后,它不得不继续回收Activity A。

3.1.1 产生的问题

此时与Acitity B正在交互的用户,点击了“返回”按钮,按照道理,应该显示Activity A才对,但是系统已经回收了Activity A。这时该怎么办呢?

系统遇到这种情况就会重新创建Activity A,重新调用它的onCreate()。

不过这里又会遇到另一个很现实的问题:如果之前的Activity A上面用户正输入了一些东西,例如他的名字和邮箱地址,或者是已经编辑了很长一大段的文字,如果系统onCreate的话,这些输入的东西就会被清除掉了。这可怎么办呢?

3.1.2 解决办法

安卓系统为我们提供了一个这种情况下数据的重建机制:在Activity被放到后台运行的时候使用onSaveInstanceState()回调函数来保存这些数据,

在Activity被重建的时候,使用onRestoreInstanceState()回调函数来恢复这些数据

需要注意的是,onSaveInstanceState()onRestoreInstanceState()在Activity周期切换过程中并不一定会被调用,只是在这种Activity异常流程处理时(Activity被系统回收、config信息变化等情况),才会被调用到。

3.2 屏幕旋转

屏幕旋转时,Activity的生命周期也将发生变化。

如果一个Activity从创建出来,到显示,然后旋转,那么它将经历:
onCreate()->
onStart()->
onResume()->
用户可以与Activity交互,此时屏幕进行旋转,从竖屏变横屏->
onPause()->
onSaveInstanceState()->
onStop()->
onDestroy()->
onCreate()->
onStart()->
onRestoreInstanceState()->
onResume()->
用户可以与Activity交互;

可以看到,旋转的时候onCreate()函数会被再次调用。在这里,如果拥有横屏布局文件,onCreate()中的setContentView()将会使用横屏的布局,如果没有,依然使用默认的布局文件。

3.2.1 产生的问题

如果Activity从竖屏变成横屏,那么会先执行onDestroy(),再进行一次onCreate()创建的过程。这意味着之前界面上显示的数据需要重新刷新一次。

假如之前刷新这些数据需要花费很长的时间,那就有必要认真的思考如何避免数据的再次刷新。

3.2.2 解决方法

解决屏幕旋转时Activity被create两次的方法有两种。

  1. onSaveInstanceState()onRestoreInstanceState()可用用来保存和还原这些数据;

  2. AndroidManifest.xml文件中,给这个Activity组件加上android:screenOrientation="orientation|screenSize"的属性就可以了;

    这种Activity从创建出来,到显示,然后旋转,那么它将经历:
    onCreate()->
    onStart()->
    onResume()->
    用户可以与Activity交互,此时屏幕进行旋转,从竖屏变横屏->
    onConfigurationChanged();

    在被触发的onConfigurationChanged()函数中,可以感知到屏幕的变化,

    如此一来,这个Activity在旋转时就不会重走销毁、创建的过程了,而只是在旋转后经历一个onConfigurationChanged()。这种情况下,即使它存在横屏布局文件,这个横屏布局也不会被使用到,因为onCreate()并没有被调用到,也就不会调用setContentView)了。


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

四大组件之Activity 第2节 Activity的生命周期

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

第2节 Activity的生命周期

每一个Activity都有它的生命周期,体现了它从诞生到消亡的各个阶段。

下图为我们展示了Activity整个生命的过程,这是安卓官方提供的Activity生命周期图。

2.1 生命各个时期的回调

Activity每进入到一个生命的阶段,就会调用这些状态对应的函数。

如果我们在代码中继承了Activity类,并覆盖了这些函数,我们就能感知到Actvity生命状态的转换,并在这个转换的时刻让Activity做对应的处理。

比如在Activity创建的时候,让它调用我们的代码,完成界面的布局;在Activity销毁的时候,让它调用我们的代码,完成各种资源的释放。

2.2 Activity的状态

接下来,我们详细介绍下Activity的各个阶段。这些阶段都是成对出现的。根据不同的标准,我们将它们分成三类:

  1. 全生命周期:这是Activity的从创建到销毁的整个阶段,从onCreate()开始到onDestroy()结束。

  2. 可见生命周期:这是Activity能被用户看到的整个阶段,这里说的能被看到包括了“虽然被显示但是不能与用户交互”的情况,例如你正在微信聊天,突然系统弹出来一个对话框类型的Activity,提示你电量不足,这时微信界面被挡在后面,不能和用户交互了,但是你还能看到。从onStart()开始到onStop()结束。

  3. 前台生命周期:这是Activity可以和用户进行交互的阶段。从onResume()开始到onPause()结束。

2.3 Acivity常见的切换周期

下面我们看看几个经常见到的Activity的周期切换。

2.3.1 完全周期

从一个Activity创建出来,到显示,再到用户按返回键主动退出销毁这个Activity,它将经历:
onCreate()->
onStart()->
onResume()->
用户可以与Activity交互,用户按返回键主动退出->
onPause()->
onStop()->
onDestroy()

2.3.2 Activity启动另一个Activity

Activity A创建出来,并显示;然后Activity A启动另一个Activity B,B创建出来,并显示,它们将经历:
Activity A onCreate()->
Activity A onStart()->
Activity A onResume()->
用户可以与Activity A交互,然后Activity A启动另一个Activity B,
Activity A onPause()->
Activity B onCreate()->
Activity B onStart()->
Activity B onResume()->
Activity A onSaveInstanceState()->
Activity A onStop()->
Activity A被隐藏,用户可以与Activity B交互;

2.3.3 Activity的自动重新创建

在某些情况下,即使用户没有点击“返回”按钮,Activity也会被系统主动回收销毁,例如,

  1. 当Activity被放在后台(OnPause或OnStop状态)没有显示出来的时候,内存紧张,系统就会主动回收这个Activity;

  2. 横竖屏切换时,Activity的界面布局发生变化需要重新载入横屏的界面布局时,就要将当前的Activity销毁,然后再重新创建一个它横屏时的Activity。

因为这是系统“悄悄”销毁的Activity,并没有得到用户的“同意”,所以当用户再次切换到这种Actiity的时候,系统需要制造出一种这个Activity从来没有被回收过的假象,它就需要“悄悄的”再把这个Activity再次创建出来。

这个过程就是Activity的重建。

不论是是因为资源不足触发的重建,还是因为屏幕旋转触发的重建,Activity的生命周期过程都一样。

这里用屏幕旋转,举个例子。如果一个Activity从创建出来,到显示,然后旋转,那么它将经历:
onCreate()->
onStart()->
onResume()->
用户可以与Activity交互,此时屏幕进行旋转,从竖屏变横屏->
onPause()->
onSaveInstanceState()->
onStop()->
onDestroy()->
onCreate()->
onStart()->
onRestoreInstanceState()->
onResume()->
用户可以与Activity交互;

在周期变化的过程当中,加入了onSaveInstanceState()onRestoreInstanceState()。虽然它们不是Activity周期的一部分,但是对它们对回调在Activity的各种切换扮演了非常重要的角色--提供了保存Activity数据的时机。

关于Activity的系统回收,我们将在下一节详细介绍。


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

四大组件之Activity 第1节 Activity的使用

第1节 Activity的使用

Activity几乎是每个应用必有的组件,所以任何安卓应用的开发几乎都是从Activity开始的。

比如,你希望设计一个计算器应用,要呈现这个计算器的功能(显示出计算器的样子,实现计算的能力)一定会在这个应用中创建一个Activity,让这个Activity展示的界面就是计算器。

使用Android Studio创建工程后,会默认为我们创建一个Activity组件,它继承自Android SDK的Activity或其派生类。

新创建的Activity–CalulatorActivity作为安卓的四大组件之一,一定要在这个应用的配置文件manifest.xml中声明自己的存在,否则系统会不认识这个组件,当你启动它的时候就会报错。


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

Application应用程序

更新时间 修改意见
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。)

开发者官网1

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

开发者官网1 开发者官网1 开发者官网1

2.2 Service

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

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

开发者官网1

2.3 ContentProvider

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

开发者官网1

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

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

2.4 BroadcastReceiver

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

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

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

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

开发者官网1

第3节 Intent初步

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

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

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

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

3.1 创建Intent

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

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

  2. 给指定的个人发货,写下接收方具体的名字和地址。这叫做显式Intent

3.2 携带数据

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

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

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

  • 继承了Serializable接口,

  • 继承了Parcelable接口,

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

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

第4节 Manifest初步

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

Manifest文件内容,大体如下:

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

4.1 application标签

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

4.2 uses-permission标签

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

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

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

5.1 Task

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

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

开发者官网1

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

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

开发者官网1

通过上面的描述,我们可以知道: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可以看做是这些组件的集合,是这些组件对外共同的名字。

开发者官网1

Application被运行起来的情况有:

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

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

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

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

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

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

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

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

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

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

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

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


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