android:应用、任务、进程、线程

来源:互联网 发布:电脑截图软件 编辑:程序博客网 时间:2024/04/29 10:24
1,Aplication 一个.apk包就可以称一个application,一般application会有很多Activity 或其他service组成。

2,task:完成用户的一个目的的所有activity 组成一个task.提到task就该提到task stack任务栈也有人叫活动栈。Android系统用一个栈来记录一个任务,既然一个任务是由许多activity组成的,那栈里存的就是所有的 activity。为什么需要记录呢?因为记录可以通过按back 键回到上一个activity.这也是为什么我们按back键可以回到上一个活动的原因。那么什么时会开启一个新的任务呢?A)Notification 启动Activity会开启一个task,因为通过notification开启activity之后不需要返回到notification,所以需要开启一个新的task,这就是为什么我们在nofication里面启动一个Activity需要设置Intent的Flag为 Intent.FLAG_ACTIVITY_NEW_TASK.

3,explicit intent 是明确指定启动哪个Activity,比如 Intent intent= new Intent(ActivityA.this, ActivityB.class).而implicit intent并不明确指定启动那个Activity,而是通过设置一些Intent Filter来让系统去帅选合适的activity来处理。为什么需要分这两种Intent呢?我觉得好处有两个:第一,Activity 的重用,当一个Activity在其manifest里设置了许多intent filter,当发生了implicit intent时,系统就会去匹配这些filter,是否符合目标。所以在设计Activity的时候就要考虑到是否重用问题,若需要重用就要设置 intent filter. 第二,Implicit intent可以让用户选择自己喜欢的Activity来处理。若在系统匹配filter时,发现多个符合目标的activtiy就会弹出对话框让用户来选择Activity.

4,启动一个Activity可以是同一个application也可以是不同的application来启动,这就是为什么每个 Activity需要自己独立的什么周期。这意味着task stack里有可能不同application的activity组成。也就是说一个task是可以有不同的application组成或者说一个 task由不同的application完成的。

Back 键与Home键 
android的手机的back键默认行为是finish处于前台的Activity的即Activity的状态为Destroy状态,再次启动该Activity是从onCreate开始的。

而Home键默认是stop前台的Activity即状态为onStop而不是Destroy,若再次启动它,则是从OnResume开始的,即会保持上次Activityd的状态。

back键也有例外的,按back键不会关闭Activity的,比如播放音乐,按了back键之后仍可以继续播放音乐,这是Music这支ap已经重写了back键的事件处理。

为什么需要Home键和Back键呢?一个使得Activity 为Stop一个使得为Destroy呢?我想原因的原因在于是android也是一个多任务的操作系统,通过Home键切换不同的任务,而通过back关闭任务中的某一个活动。若仔细想想就觉得PC的多任务行为一样的。

应用程序模型:应用、任务、进程、线程 
在多数操作系统中,在应用程序驻留的可执行映像文件、运行的进程和用户交互的图标和应用之间有强1对1的关系。在Android操作系统中,这些关联更多的是不固定,重要的是理解不同的部分怎么整合在一起。
因为Android应用成需的灵活的特性,当实现程序的各个部分的时候,有一些基本术语需要理解。
1、android包(简称.apk)是包容程序代码和资源的文件。这也是发布应用程序的文件,当用户在其设备上安装应用程序时,由用户下载这个文件。
2、一般一个任务是用户觉察出的作为一个能运行的应用程序的东西:通常一个任务在HOME屏幕有一个图标,通过这个图标可以被用户访问,作为顶层条目,任务可获得,能在其他任务前面放到前台。
3、进程是低级核心处理过程,用于运行应用程序代码。通常,在.apk中的所有代码只运行在一个进程中,每个.apk都有专用的进程。但是,进程标签能用于修改代码运行的地方,要么针对整个.apk,要么针对单个活动、接收器、服务、提供者、组件。

任务

这里关键点:当用户看到认为他们是一个应用程序时,实际上处理的东西就是一个任务。如果你仅仅创建一个带有大量活动的.apk,其中一个活动是顶级入口点(通过一个intent过滤器针对操作android.intent.action.MAIN和分类 android.intent.category.LAUNCHER),那么的确有一个任务针对你的.apk创建起来,从这里启动的任何活动也作为那个任务的一部分运行。
一个任务,来自用户的眼中看,是应用程序;从程序开发者眼中看,是一到多个活动,用户已经越过进入那个任务,但是还没有关闭,或者,一个活动堆栈。一个新任务是通过使用Intent.FLAG_ACTIVITY_NEW_TASK 标志启动一个活动Intent来创建的;这个Intent会用于作为任务的根Intent,定义是什么任务。任何没有使用这个标志启动的活动会运行在和正在运行的那个活动所在的相同的任务中(除非活动已经请求一个特殊的启动模式,稍后讨论)。任务能被排序:如果你使用FLAG_ACTIVITY_NEW_TASK 但是已经有一个任务运行于那个Intent,当前任务的活动堆栈会送到前台而不是启动一个新的任务。
FLAG_ACTIVITY_NEW_TASK 必须小心地单独使用:使用这个标志就说明,从用户的角度看,一个新的应用程序在这个点启动。如果这不是你喜欢的行为,你应该不创建一个新任务。另外,如果用户可能从HOME屏幕回退到原来的位置,你应该仅仅使用新任务标志,以运行和新任务同样的Intent。否则,如果用户从正在运行的任务中按下HOME键而不是BACK键,你的任务机器活动将会在home屏幕之后被排序,而没有办法返回。

任务亲和力

在一些情况下,Android需要知道活动属于哪一个任务,即使当活动没有运行在指定的任务中时。这是通过任务亲缘关系完成的,任务亲缘关系提供一个唯一的任务静态名称,一到多个活动打算运行在具有静态名称的任务中。一个活动默认的任务亲和力是实现活动的.apk包的名称。这就提供了通常的可期望的行为,其中,在指定.apk文件中所有活动对用户来说是单个应用程序的一个部分。
当启动一个新活动而不是Intent.FLAG_ACTIVITY_NEW_TASK 标志的时候,任务亲缘关系没有影响新活动运行的任务:总是运行在触发任务的活动的任务中。但是,如果NEW_TASK被使用,那么亲缘关系会用于决定一个任务是否和一个相同的亲缘关系已经存在。如果是已经存在,那么任务将会被提到前台,新活动运行在那个任务的顶层。
这种行为对于必须使用NEW_TASK标志的情况是非常有用的,特别是从状态栏通知或者home屏幕快捷方式运行活动时。结果是:当用户使用这种方式运行你的程序时,当前任务状态会拉到前台,用户现在想看到的活动被放到顶层。
你能在manifest的应用程序标签中指定你自己的任务亲缘关系,针对.apk的所有活动,或者针对单个活动的活动标签。怎么使用亲缘关系的例子如下:
1、如果你的.apk包含多个顶层的用户能运行的应用程序,那么你会可能想分派不同的亲和力到用户从你的.apk中找到的每个活动。使用不同的名称的好的惯例是添加你的.apk包名称,使用克隆的独立的字符串。例如,"com.android.contacts".apk文件可能有亲缘关系"com.android.contacts:Dialer" 和 "com.android.contacts:ContactsList"。
2、如果你正在替换通知、快捷方式、其他内嵌的在内部运行的活动,那么你可能需要显式设置你替换的活动的任务亲缘关系为与你替换的应用程序相同。例如,如果你正在替换通讯录详细视图(用户可以创建和调用快捷方式),那么你会想设置任务亲缘关系到"com.android.contacts"。

运行模式和运行标志

控制活动和任务交互的主要方法是通过活动的launchMode属性和与Intent关联的标志。这两个参数能一同工作在控制活动运行的结果的各种方法之下,正如在关联文档中描述的那样。在这里,我们将会看到一些常用的用例和这些参数的组合。
最常用的运行模式(除了默认的标准模式外)是singleTop。这不会对任务有影响,这种模式恰好避免不同时间启动同一个活动(在堆栈顶层)
singleTask 运行模式对任务有一个主要的影响:导致活动总是启动在新任务里(或者,已存在的任务被拉到前台)。使用这种模式要求关心怎么和系统的其他部分交互,因为它影响到活动的每个路径。这种模式应该仅被用于作为应用程序前门的活动(即,支持MAIN操作和LAUNCHER分类)
singleInstance运行模式更多地是专用的,应该仅仅用于完全作为一个活动来实现应用程序的情况下。
你经常会运行进入的一种情况是另外一个实体(比如:SearchManager、NotificationManager)启动你的其中一个活动。在这种情况下,Intent.FLAG_ACTIVITY_NEW_TASK 标志必须使用,因为活动在任务的外部启动(应用程序和任务甚至可以不存在)。正如前面描述的,这种情况下的标准行为是,把当前任务提到前台,当前任务匹配新活动的affinity,并在顶层启动新活动。但是,有您能实现的其他类型的行为。
一个普通的方法是,与NEW_TASK一起使用Intent.FLAG_ACTIVITY_CLEAR_TOP标志。通过这样做,如果你的任务已经在运行,那么将会被提到前台,堆栈中的所有活动将被清除,除了根活动,根活动的onNewIntent(Intent)在Intent被启动的时候被调用。注意,当使用这种方法的时候,活动经常使用singleTop或者singleTask运行模式,因此,当前实例给予新Intent而不是请求销毁和产生新实例。
你能采用的另外一个办法是,设置通知活动的任务affinity为空串(表示无affinity),并设置 finishOnBackground属性。这种办法是有用的,如果你将会希望通知把用户带到一个分离的活动,胜于返回到应用程序的任务。通过指定这个属性,不论用户是否使用BACK或者HOME离开活动,活动都会完成。如果属性没有被指定,按HOME将会导致进入活动,其任务保持在系统中,可能没有办法返回。
保证阅读launchMode属性和Intent标志相关文档,以了解这些选项。

进程

在Android操作系统中,进程完全是应用程序的具体实现,不是用户通常认为的那种东西。他们的主要用途是简单的:
1、改善稳定性或者安全性,通过把未信任或者不稳定的代码放入独立的进程的方法来解决
2、简化在同一进程中多个.apk文件的代码的运行
3、有助于系统管理资源,通过吧重量级代码放入独立的进程,可以被杀掉,而且和程序的其他部分无关。
正如前面描述的那样,进程属性用于控制细小程序组件运行的进程。注意,这些进程属性不能用于违反系统安全规则:如果没有共享同一个用户ID的两个.apk文件试图运行在同一个进程中,那么,这是不允许的,不同的进程将会分别针对每个.apk文件被创建。
参见安全相关的文件了解更多的关于安全规则的信息。

线程

每个进程有一到多个线程运行在其中。在多数情况下,Android避免在进程中创建额外的线程,保证应用程序是单线程的,除非应用程序自己又创建了线程。重要印证是,注意,新线程不会针对每个Activity/BroadcastReceiver/Servie/ContentProvider实例:这些程序组件在对应的进程中实例化(除非另作说明所有的组件都位于同一个进程),在那个进程的主线程中。这意味着,当被系统调用的时候,没有组件(包括服务)应该在进程中执行长的或者阻塞的组件(例如网络调用或者计算循环),因为这将会阻塞所有进程中的其他组件。你可以使用标准库线程类或者Android的 HandleThread类来在另外一个线程中执行长操作。
There are a few important exceptions to this threading rule:
线程规则有几处例外:
1、到IBinder的访问或者在IBinder上实现的接口从调用它们的线程被调度,或者如果来自其他进程则从本地进程中的线程池被调度,不是从他们的进程的主线程被调度。特别地,到服务的IBinder的访问将会以这种方式调用。(虽然到在服务自身的调用来自主线程。)这意味着,IBinder接口的实现必须总是在线程安全模式下编写,因为他们能在同一时间从许多随机线程中被调用。
2、到ContentProvider的调用从调用线程或者IBinder所在的主线程被调度。在ContentProvider类的相关文档中这个方法有描述。这意味着,这些方法的实现必须总是以线程安全方式编写,因此,他们能在同一时刻从许多随机线程被调用。
3、在View和它的子类上调用来自视图窗口运行的线程。正常情况下,这将会是进程的主线程,但是如果你创建一个线程,然后从线程中显示一个窗口,那么这个窗口的视图层次将会从那个线程被调用。