全面了解Activity

图片 1Image.png

摘自http://ju.outofmemory.cn/entry/145454

世家好,作者叫石头

事先在斟酌Android 两种LaunchMode的时候,有看齐有关taskAffinity的开始和结果,当时髦无细看,以往意料之外开采同事提交代码的时候有写关于修改taskAffinity的东西,于是就有抽时间详细的研商了一晃taskAffinity那一个性情,开掘还蛮复杂的,把团结的一部分实行和见地写下去,供今后翻看,涉及到的开始和结果非常多,能够器重查阅石青的书体。

信任大家都知晓Android中的4大组件(Activity活动,Service服务,ContentProvider剧情提供者,BroadcastReceiver播音接收器),Activity是我们采用最多的也是最中央的机件,Activity提供窗口和顾客实行交互.

读书Android最佳的课本就是谷歌(Google)官方文书档案加代码实行,在起来讲taskAffinity属性从前,大家可以先看一下官网对于Task的概念:

Android中的activity清一色归属于task管理(task是三个持有栈结构的器皿),task是多个activity的汇集,android默许景况会为各类App维持贰个task来存放app的所有activity(当然那只是私下认可情况),task的默认name为该apppackagename

A task is a collection of activities that users interact with when 
performing a certain job. The activities are arranged in a stack 
(the back stack), in the order in which each activity is opened.

当然大家也足以在AndroidMainfest.xml中申明activity的 taskAffinity 属性来自定义task,不过不建议使用,因为如果别的app也注脚了同样的task,那个app可能运行到你的activity,那样会拉动各样安全难题(举个例子获得您的Intent).

一句话来说:task便是一组特定的activities集结,这个activities依据每三个被张开的依次放到三个stack中。

地点我们介绍过了,系统是通过task的方式来管理activity的,当多少个新的activity开端的时候,该activity会被放置在货仓(back stack)的顶端,成为正在运行的移动,从前的activity始终维持低于它在仓房,而不会冒出在前台.

当客户展开三个application的时候,该application的task来到前台,如果未有该application的task存在(application近些日子不曾被张开过),叁个新的task将会被创立同期应用程序的主activity作为根activity在stack中开垦。
当当前的activity运转另三个activity的时候,新的activity被推到栈顶并收获主旨,此前的activity还是在stack中,不过被stop了。当叁个activity stop了,系统一保险留其UI的当下情形。当顾客按重返键,当前的activity从栈顶被弹出(被destroy了),以前的activity 恢复生机(resume)。栈中的activities重不会再一次被排序,独有进栈和出栈。那样一来,重临stack以一种先进后出的指标协会进行操作。下图通过三个时光轴表未来不可同日而语的时辰点属于当前回去stack的activities之间的快慢来可视化那个行为。

官方activity_lifecycle:

图片 2

图片 3activity

diagram_backstack.png

当大家开拓一个新的activity实例的时候,系统会以此调用

就算客户继续点击重回键,直到全数的activities从栈中被移除,task将不再存在。
三个task是一个有机的完好,当客户最先了七个新的task可能经过Home键来到Home screen,能够被移到后台。在后台,全数task中的activities被stop了,但是这么些task的回到stack依旧保持不改变-改task只是轻巧地不见了关子,被另一个stack替代,如下图所示:

onCreate() -> onStart() -> onResume() 然后初叶running

图片 4

activity在running的时候要是被覆盖(张开新的activity,或然被锁屏,不过它依旧在前台运转,lost focus but is still visible),系统就能够调用onPause();

diagram_multitasking.png

onpause()艺术中,大家一般会提交未保存的转移到漫长化数据,甘休动画和别的东西.但是我们要明了未来这几个activity仍旧完全活着(它保存全体的气象和成员音讯,并且保留到窗口管理器的总是)

八个task能够回到到前台那样客商就足以在她们相差的地点重新拿起。假若,举个例子,当前的task(Task A)有多少个activities在它的栈中-三个在此时此刻的activity上面。顾客按下Home键,然后运行另四个新的应用程序。当回到Home screen的时候,Task A步向到了后台,当新的应用程序运行的时候,系统运行了该应用程序的带有它本身activities栈的task(Task B)。在和新的应用程序交互后,客户在此重返到Home而且接纳最先运维的Task A的应用程序。未来,Task A重新来到前台-全部的多少个在它在栈中的activities都完美而且栈顶的activity复苏了。这年,客户能够切换回Task B通过回到Home并选拔对应task的应用程序。那正是Android的多任务的例证。

  • 1.启动Activity:系统会先调用onCreate措施,然后调用onStart形式,最终调用onResumeActivity进去运维景况。
  • 2.当前Activity被其他Activity蒙面其上或被锁屏:系统会调用onPause方式,暂停当前Activity的执行。
  • 3.当前Activity由被覆盖意况回到前台或解锁屏:系统会调用onResume艺术,再一次步向运转状态。
  • 4.当前Activity转到新的Activity分界面或按Home键回到主屏,自个儿退居后台:系统会先调用onPause方法,然后调用onStop主意,步向停滞状态。
  • 5.客商后倒退到此Activity:系统会先调用onRestart主意,然后调用onStart艺术,末了调用onResume方式,再次步入运市价况。
  • 6.当前Activity地处被遮住意况大概后台不可知状态,即第2步和第4步,系统内部存款和储蓄器不足,杀死当前Activity,而后客户退回当前Activity:再次调用onCreate方法、onStart方法、onResume措施,踏入运市价况。
  • 7.客商退出当前Activity:系统先调用onPause主意,然后调用onStop艺术,最终调用onDestory格局,甘休前段时间Activity

因为重回栈中的activities一向都不会被另行排序,假如你的应用程序允许客户运行一个一定的根源不独有叁个activity的activity。该activity的四个新的实例被成立并被push盗栈上(实际不是将其它改activity在此以前的实例带到栈顶)。那样一来,你的应用程序中的贰个activity大概会被早先化数次(以至来自分歧的tasks),如下图所示:

onSaveInstanceState:在Activity被遮住或退居后台之后,系统能源不足将其杀死,此方法会被调用;在客户改造荧屏方向时,此办法会被调用;在此时此刻Activity跳转到别的Activity或者按Home键回到主屏,自己退居后台时,此方法会被调用。第一种景况大家不能保障哪天发生,系统依据能源恐慌程度去调解;第三种是显示屏翻转方向时,系统先销毁当前的Activity,然后再重新建立一个新的,调用此方法时,我们得以保留一些暂且数据;第二种景况系统调用此措施是为着保留当前窗口各类View组件的境况。onSaveInstanceState的调用顺序是在onPause之前。

onRestoreInstanceState:在Activity被掩盖或退居后台之后,系统财富不足将其杀死,然后客商又回到了此Activity,此措施会被调用;在客户改换荧屏方向时,重新建设构造的历程中,此方法会被调用。大家能够重写此办法,以便能够还原部分一时数据。onRestoreInstanceState的调用顺序是在onStart之后。

图片 5

activity被回收的动静和消息保存和重振旗鼓进程

public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { if(savedInstanceState!=null){ //判断是否有以前的保存状态信息 savedInstanceState.get; } super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Overrideprotected void onSaveInstanceState(Bundle outState) { // TODO Auto-generated method stub //可能被回收内存前保存状态和信息, Bundle data = new Bundle(); data.putString("key", "last words before be kill"); outState.putAll; super.onSaveInstanceState;} @Overrideprotected void onRestoreInstanceState(Bundle savedInstanceState) { // TODO Auto-generated method stub if(savedInstanceState!=null){ //判断是否有以前的保存状态信息 savedInstanceState.get; } super.onRestoreInstanceState(savedInstanceState);}} 

onSaveInstanceState()方法,在activity被回收在此以前调用,用来保存本身的情形音讯,以便回收后重新建立时上升数据(在onCreate()onRestoreInstanceState()中回复).旋转荧屏重新建立activity会调用该情势,但任何意况在onRause()onStop()气象的activity不明显会调用,下边是合罗马尼亚语档表达:

 One example of when onPause and onStop is called and not this method is when a user navigates back from activity B to activity A: there is no need to call onSaveInstanceState on B because that particular instance will never be restored, so the system avoids calling it. An example when onPause is called and not onSaveInstanceState is when activity B is launched in front of activity A: the system may avoid calling onSaveInstanceState on activity A if it isn't killed during the lifetime of B since the state of the user interface of A will stay intact. 

也便是说,系统灵活的来支配会不会调用该措施,不过一旦要调用就必定发生在onStop方式在此以前,但不保证发生在onPase的前面依然前边.

onRestoreInstanceState()该措施在onstartonPostCreate中间调用,当然我们也足以在onCreat中还原以前大家在onSaveInstanceState()中保存下去的多寡,然而我们不时必要在发轫化布局造成今后再回复数据,那是就能够在onRestoreInstanceState()中恢复生机数据.onPostCreate():一般大家都不曾兑现这一个方法,它的功能是在代码最早运维在此以前,调用系统做最后的伊始化职业.

简易点说就是:定义activity实例与task的关联格局

为了完结暗许运转(standard)格局之外的需要:

  • 让某个activity启航叁个新的task(实际不是被纳入当前task)
  • 让activity运营时只调用已有的有些实例(并非在back stack(此前大家有涉及过哟) 顶创立叁个新的实例)
  • 当客户距离task时只想保留根activity,而back stack中的其余activity都要清空.

diagram_multiple_instances.png

概念运行格局的不二秘诀有2种:
  • 使用manifest文件定义
  • 使用Intent申明定义

动用manifest文件定义运营形式:在 manifest 文件中activity申明时,利用 activity 成分的 launchMode 属性来设定 activity 与 task 的涉及。

<activity ...... android:launchMode="standard" > .......</activity>

小心: 你用 launchMode 属性为 activity 设置的形式能够被运营 activity 的 intent 标识所覆盖,代码的优先级最高。

当今我们掌握了怎么定义运转格局了,但是有何样运维格局呢?

  • standard 当通过这种格局运行activity时,Android总会为目的Activity创立三个新的实例(在此以前有过也会再也创建),并将该Activity增加到日前Task栈中。这种措施不会运维新的Task,只是将新的 Activity增添到原本的Task中。

图片 6

  • singleTop该情势和standard方式基本一致,但有点例外:当将在被运营的Activity已经放在Task栈顶时,系统不会再次创造目的Activity实例,而是一向复用Task栈顶的Activity。

图片 7

  • singleTaskActivity在同一个Task内独有二个实例。若是将在运维的Activity不设有,那么系统将会创设该实例,并将其加盟Task栈顶;

一经将在运营的Activity已存在,且存在栈顶,直接复用Task栈顶的Activity。

假如Activity存在可是尚未放在栈顶,那么此时系统会把放在该Activity上边的有所其余Activity全体移出Task,进而使得该指标Activity位于栈顶。

图片 8

  • singleInstance 无论从哪些Task中运营目的Activity,只会创设八个对象Activity实例且会用二个斩新的Task栈来装载该Activity实例.

一经将在运营的Activity不设有,那么系统将会先成立三个斩新的Task,再创制指标Activity实例并将该Activity实例放入此全新的Task中。

假设将在运转的Activity已存在,那么不论它投身哪个应用程序,哪个Task中;系统都会把该Activity所在的Task转到前台,进而使该Activity显示出来。

和"singleTask"类似,独一不相同的是系统不会在这些activity的实例所在的task中运行任何另外activity。

其一activity的实例永世是其一task中的唯一一个成员,这一个activity运营的别的别的activity都将要别的的task中开荒。

图片 9

动用Intent标记定义运行格局:

  • FLAG_ACTIVITY_NEW_TASK和事先研商过的"singleTask"一样,在新的task中运维activity,假如一个您必要的activity的task已经存在,则将它助长前台,复苏其上三个气象,它通过onNewIntent()收到这几个新的intent。

  • FLAG_ACTIVITY_SINGLE_TOP和"singleTop"行为等同,借使被运营的activity是眼前顶端的activity,则早已存在的实例收到 onNewIntent(),并不是新建实例。

  • FLAG_ACTIVITY_CLEAR_TOP假定被启动的activity已经在当下task运营,不创建它的新实例,而是销毁在它之上的任何具备activities,然后经过 onNewIntent()传递三个新的intent给那些恢复生机了的activity。 那些作为在 launchMode 中从不对应的属性值。 注意,假若activity的开发银行情势是"standard",它自身也将被移除,然后二个新的实例将被运维。 那是因为当运转形式是"standard"时,为了接收新的intent必需创建新的实例。

那样一来,借使顾客点击重回键,该activity的每贰个实例根据它们被张开的逐个显透露来。不过,你可以修改这种行为一经你不想一个activity被实例化数十三遍。

处理affinities

Affinity提示了activity更偏侧于属于哪个task。 暗中同意情形下,同三个利用的activities侧向于在同三个task中。你能够透过<activity>标签中的 taskAffinity来修改这种作为。 详细内容请查看:API Guides: Tasks and Back Stack

简短总计如下:
1、当Activity A运维 Activity B,Activity A is stopped,可是系统依旧保留其景况(比方滚动轴地方和表单中的文字啊)。要是顾客在Activity B点击再次回到键,Activity A从它存储的情景中回复。

敞开二个task

您可以通过给activity三个intent filter(action是"android.intent.action.MAIN",category是"android.intent.category.LAUNCHE帕杰罗"),让这一个activity是三个task的进入点。

如下:

<activity ... > <intent-filter ... > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> ...</activity>

四个如此的intent filter会使得那几个activity的icon和label呈现在程序运转处,提供了一种艺术,使得客商能够运行那么些activity,当它运转后,客户也能够通过它来回到到那么些task。 第二个力量是相当重大的:客户必需能够离开一个task,然后经过activity launcher再次来到到它。 因为那个缘故,多少个让activity长久实例化一个task的开发银行格局:"singleTask" 和"singleInstance",应该仅在activity有叁个 ACTION_MAIN 和CATEGORY_LAUNCHEPAJERO filter的时候用它们。

2、当客户通过点击Home键离开贰个职分,当前的Activity停止了,它的task转到后台。系统保留task中每二个activity的景况。假若客户稍后选用起来该task的运用Logo来平复该task,该task就能赶来前台并回复栈顶的activity。
设若客户点击再次来到键,当前的activity被从栈中弹出并被destroy。栈中在此之前的activity被还原,当叁个activity被destroy,系统将不会保留改activity的动静。

迄今截止,相信大家对Activity有了越来越深的询问了啊~~~

3、Activities能够被实例化数10次,即便来自别的tasks。

下边大家看看官方网址关于处理Task的源委,那么些就是LaunchMode和taskAffinity紧凑相关了。

Android管理任务的法子和back stack,如上面描述的同样-通过”先进后出”放置全部在同贰个task中穿插开垦的activities-对于大多数应用程序都干活的很好,你不要忧虑您的activities怎么样与task关联或许他们怎样存在于back stack中。然则,你恐怕调节你想不通常常的措施。恐怕你想你应用程序中的二个activity起始一个新的task当它运转的时候(并不是被停放在脚下task中);或许,当您运维贰个activity,你想讲它的二个留存的实例带到前台(而不是在back stack的栈顶重新成立一个它的实例);可能,你想当客商距离task的时候,你的back stack中具备的activities被拔除除了根activity。

您能够做这一个事情或然越多,使用activity manifest成分中的属性和intent标记你传给startActivity()方法的。
下边作者将应用到的显要activity属性如下:taskAffinity launchMode和部分首要的intent标记:

FLAG_ACTIVITY_NEW_TASK
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_SINGLE_TOP

依附谷歌 Android官方文档的建议:

1、定义运行情势:
运行形式允许你定义二个activity的实举个例子何与当下的task关联,有几种方法来定义不相同的开发银行情势:
利用manifest配置文件
当您在你的manifest文件中宣称多个activity时,你能够指明activity怎样和tasks关联当它运行的时候。

2、使用intent标志
当您调用startActivity()的时候,你可以包含两个声称新的activity怎样和当前的task关联的intent。
那样,借使Activity A运营Activity B,Activity B能够在它的manifest文件中定义它什么与当前任务关联而且Activity A也足以乞请Activity B应该如何和日前task关联,借使五个activities都定义了Activity B应该如何与叁个task关联,那么Activity A的呼吁(在intent中定义的)优先于Activity B的呼吁(定义在manifest的质量)。

选用manifest配置文件:
launchMode属性指明activity怎么着被运行到task的命令,有各样分化的开发银行形式你能够赋值给launchMode属性:

standard"(私下认可方式)
暗中同意地,系统在task中创制三个从它被运维和路由intent到它的activity的实例,activity能够被实例化多次,每叁个实例能够属于不一致的tasks,并且三个task能够用多少个实例。

singleTop
就算三个activity的实例早就经存在于当下task的顶上部分,系统将经过调用它的onNewIntent()方法路由该intent到该实例,而不是开创三个该activity的新实例。activity能够被实例化多次,各样实例能够属于分裂的tasks何况八个task能够具有两个实例(但只有在stack栈顶的activity不是该activity的存活实例)。
假设二个task的归来stack由根activity A,activity B,C和栈顶的activity D组成(栈是A-B-C-D;D在栈顶),三个针对性activityD的intent央浼到来了。如若D具备暗中同意的”standard”运行格局,D类的贰个新的实例被运维了,back stack就变出了A-B-C-D-D。但是假设Activity D的开行形式是”singleTop”,已经存在的D的实例会透过onNewIntent()方法收到该央浼,因为D在栈顶-该栈照旧是A-B-C-D。然后一旦三个针对性类型B的央求达到了,接着B的三个新实例被增多到stack中,就算它的起步格局是”singleTop”,此时栈是A-B-C-D-B。

singleTask
系统会创制三个新的task而且实例化该task的root activity,然后借使该activity的贰个实例早就经存在二个单身的task中,系统将通过调用onNewIntent()方法路由该intent到存在的实例,实际不是创建叁个新的实例,二个时光该activity只有叁个实例能够存在。
小心:尽管activity运营在贰个新的task中,可是重返键照旧带客商回到在此之前的activity中。

singleInstance
和singleTask类似,除了系统不会运转任何别的activities到具备实例的task中,该activity总是它的task的独门和唯一成员,任何别的被这么起步的activities都在贰个单独的task中打开。

再看二个例子:Android浏览器接纳注解web browser activity应当总是在它本人的task中展开-通过在<activity>成分中钦定singleTask运营方式。
那代表倘令你的应用程序发送二个intent央求展开Android Browser,Android Browser的Activity不会停放和您的采纳同叁个task中。相反,要么七个针对性Browser的新的task运维,或然只要早就经有了三个Browser的task在后台运转,该task将会转到前台管理新的intent。
甭管贰个activity是在一个新的task中运行,依然和运转它的activity处于同多个task,再次回到键总是能够带客商回到在此以前的activity。
不过,假设您运转activity的时候内定singleTask运营情势,接着假如该activity的四个实例存在于叁个后台task中,那全体task会被带到前台,这年,回降栈(back stack)栈顶现在席卷带到前台的task中的全部activities。
如下图所示:

图片 10

diagram_backstack_singletask_multiactivity.png

地点的示例图很清晰明了,一个回顾证明为singleTask运维情势的Activity X和Activity Y的后台task,当Activity Y被前台activity 2所运转的时候,整个后台task都会增加到back stack中,此时back stack中就有多少个activities了,若是此刻顾客点击重临键回落到的是Activity X并非想象中的Activity 2.

使用Intent标志:
当运行二个activity时,你能够修改一个activity和它的task的关联性通过在你用startActivity()方法传递的intent中蕴藏标记,你能够满含的标识
FLAG_ACTIVITY_NEW_TASK
开发银行钦赐activity到一个新的task中,要是贰个提到你未来正在起步的activity的task,该task将会以它提起底存款和储蓄的意况被带到前台况兼改activity在它的onNewIntent()方法中吸收接纳新的intent。一样与地点的singleTask。
FLAG_ACTIVITY_SINGLE_TOP
万一正在起步的activity是近来activity(在back stack栈顶),那么存在的实例将会在接受三个onNewIntent()的调用,并非新成立二个该activity实例,同样与地点的singleTop。
FLAG_ACTIVITY_CLEAR_TOP
如若正在起步的activity早就经运维在当下的task中,此时不会另行启航一个该activity的实例,而是具备在该activity上面其余的activities会被destroy,而且intent通过onNewIntent()方法会被发送到恢复生机的activity实例(今后栈顶的activity)。
FLAG_ACTIVITY_CLEAR_TOP是配合FLAG_ACTIVITY_NEW_TASK最长使用的。当三只利用的时候,那几个标识是平昔在另贰个task中已存在的activity并把它内置能够响应intent的岗位的一种艺术。
小心:借使一定的activity的启航航空模型型式是standard,它也会被从栈顶移除并且贰个新的实例在它的地方被运营来管理进来的intent,因为当运营情势是standard时,一个对准新的new intent的新的实例总会被创立。
处理affinities
affinity属性指美赞臣(Meadjohnson)个activity更欣赏属于哪个task。私下认可地,来自四个应用程序的具有activities互相都有叁个亲和性。所以,一般的话一个长期以来应用的享有activities偏向于在三个一直以来的task中。但是,你能够修改二个activity的默许affinity属性。定义在不一致应用程序的activities可以共享二个affinity属性,恐怕定义在同贰个应用程序的activities能够被给予分裂的task亲和性。
您能够经过<activity>成分的taskAffinity来修改任何给定的activities的亲和性。

taskAffinity属性带有二个字符串值,该值必需和注解在manifest中的默许包名相同独一,因为系统应用这么些名字来鉴定分别应用程序的私下认可task亲和性。

亲和性使用在三种景况下:
当三个包含FLAG_ACTIVITY_NEW_TASK标记的intent运行二个activity时。

八个新的activity,暗中认可地开发银行到调用startActivity()方法的activity的task中。它和调用者放到一样的back stack中。不过,若是传递给startActivity()的intent富含FLAG_ACTIVITY_NEW_TASK标识,系统将会需找一个不等的task来包容新的activity。常常,它是一个新的task。可是,不是必得都以如此的。借使已经存在一个和新的activity具备同样的affinity的task,新activity会运转到该task中。若无,它会运营三个新的task。
万一该标识变成多少个activity去最初三个新的task并且当顾客按Home键的相距该task的时候,确定有局地方式对顾客来讲去重返该task。一些实体(像打招呼管理)总是运营activities到贰个外表的task,而非作为到她们友善的task的一部分,所以他们接二连三将FLAG_ACTIVITY_NEW_TASK放到他们传递给startActivity()的intents中。倘若您有二个方可被外表实体调用的activity能够运用该标记,确定保障客商有二个独门的不二秘诀赶回到曾经起步的task中,比如一个开发银行图标(task的根activity有一个CATEGOEscortY_LAUNCHER intent过滤器)
当三个activity它的allowTaskReparenting属性设置为true

这种场所,activity能够从它运维的task移到和它有同样affinity的task,当该task来到前台的时候。
譬喻,固然四个告诉选定的都会的气候景况的activity作为三个游览应用程序的一有个别。它和同应用程序的任何activities有平等的affinity(暗中同意的选用程序affinity)况且它通过allowTaskReparenting属性允许重排。当你的多少个activity运行天气报纸发表那一个activity时,它最早属于和你的activity一样的task。可是,当游历应用的task来到前台的时候,天气电视发表的activity被重新分配到该应用程序的task中并彰显它。
留神:借使三个.apk的文本从客商角度看蕴涵不独有二个应用,你可能想采用taskAffinity属性去分配区别的亲和性给和各类应用关联的activities。
接轨看官方网站对于taskAffinity属性的定义(水平有限,翻译的不是很好):

Activity具有对于特定task的亲和性(affinity),具备同样的亲和性(affinity)的Activities概念上属于同一的task(从客户的角度来看就是一样的application),三个task的亲和性(affinity)由它的根activity的亲和性决定.亲和性决定两件事:activity重新向父的task和task所包容的activity,当它被全部FLAG_ACTIVITY_NEW_TASK标识所运营。
默许景况下,同一个application中具备的activities具备相同的亲和性(affinity).你能够设置改属性来把它们分组界别,以致放置那多少个被定义在差别的application中的activities到同贰个task。要钦命activity不抱有别的task的亲和性,只需安装该属性为空字符串。
假若该属性未有被安装,activity私下认可承接application的亲和性(affinity)设置,多个application的默许亲和性名称在<manifest>成分中被安装为包名。

本文由华夏彩票发布于编程应用,转载请注明出处:全面了解Activity

您可能还会对下面的文章感兴趣: