国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

Andoid Activity四大啟動(dòng)模式

2019-11-09 15:42:22
字體:
供稿:網(wǎng)友

眾所周知當(dāng)我們多次啟動(dòng)同一個(gè)Activity時(shí),系統(tǒng)會(huì)創(chuàng)建多個(gè)實(shí)例,并把它們按照先進(jìn)后出的原則一一放入任務(wù)棧中,當(dāng)我們按back鍵時(shí),就會(huì)有一個(gè)activity從任務(wù)棧頂移除,重復(fù)下去,直到任務(wù)棧為空,系統(tǒng)就會(huì)回收這個(gè)任務(wù)棧。但是這樣以來,系統(tǒng)多次啟動(dòng)同一個(gè)Activity時(shí)就會(huì)重復(fù)創(chuàng)建多個(gè)實(shí)例,這種做法顯然不合理,為了能夠優(yōu)化這個(gè)問題,Android提供四種啟動(dòng)模式來修改系統(tǒng)這一默認(rèn)行為。

Activity的四種啟動(dòng)模式:

standard、singleTop、singleTask、singleInstance

接下來,我們一邊講理論一邊結(jié)合案例來全面學(xué)習(xí)這四種啟動(dòng)模式。 為了方便打印,定義一個(gè)BaseActivity,在其onCreate方法和onNewIntent方法中打印出當(dāng)前Activity的日志信息,主要包括所屬的task,當(dāng)前類的hashcode,以及taskAffinity的值。之后我們進(jìn)行測(cè)試的Activity都直接繼承該BaseActivity

public class BaseActivity extends Activity { @Override PRotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.i("owen", "onCreate method " + getClass().getSimpleName() + " taskId: " + getTaskId() + " hasCode: " + this.hashCode()); dumpTaskAffinity(); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); Log.i("owen", "onCreate method " + getClass().getSimpleName() + " taskId: " + getTaskId() + " hasCode: " + this.hashCode()); dumpTaskAffinity(); } protected void dumpTaskAffinity() { try { ActivityInfo info = this.getPackageManager().getActivityInfo(getComponentName(), PackageManager.GET_META_DATA); Log.i("owen", "taskAffinity " + info.taskAffinity); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } }}

Standard-默認(rèn)模式

這個(gè)模式是默認(rèn)的啟動(dòng)模式,即標(biāo)準(zhǔn)模式,在不指定啟動(dòng)模式的前提下,系統(tǒng)默認(rèn)使用該模式啟動(dòng)Activity,每次啟動(dòng)一個(gè)Activity都會(huì)重寫創(chuàng)建一個(gè)新的實(shí)例,不管這個(gè)實(shí)例存不存在,這種模式下,誰啟動(dòng)了該模式的Activity,該Activity就屬于啟動(dòng)它的Activity的任務(wù)棧中。這個(gè)Activity它的onCreate(),onStart(),onResume()方法都會(huì)被調(diào)用。

Manifest 中的配置形式:

<activity android:name=".standard.StandardActivity" android:launchMode="standard" >

使用案例:

對(duì)于standard模式,android:launchMode可以不進(jìn)行聲明,因?yàn)槟J(rèn)就是standard。 StandardActivity 的代碼如下,入口MainActivity啟動(dòng)會(huì)直接啟動(dòng)該Activity,這個(gè)Activity中又有一個(gè)按鈕啟動(dòng)StandardActivity。

public class ActivityStandard extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_standard); TextView jumpButton = (TextView) findViewById(R.id.standard); jumpButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(ActivityStandard.this, ActivityStandard.class); startActivity(intent); } }); }}

我們首先進(jìn)入StandardActivity,進(jìn)入后再點(diǎn)擊進(jìn)入Standard的按鈕,再按四次返回鍵不斷返回。

打印日志如下:

02-08 11:11:58.192 11356-11356/com.ownchan.activitystartmodel I/owen: onCreate method MainActivity taskId: 358 hasCode: 53114957402-08 11:11:58.193 11356-11356/com.ownchan.activitystartmodel I/owen: taskAffinitycom.ownchan.activitystartmodel02-08 11:11:58.217 11356-11356/com.ownchan.activitystartmodel I/owen: onCreate method ActivityStandard taskId: 358 hasCode: 66355035402-08 11:11:58.218 11356-11356/com.ownchan.activitystartmodel I/owen: taskAffinitycom.ownchan.activitystartmodel02-08 11:12:04.402 11356-11356/com.ownchan.activitystartmodel I/owen: onCreate method ActivityStandard taskId: 358 hasCode: 24776541602-08 11:12:04.402 11356-11356/com.ownchan.activitystartmodel I/owen: taskAffinitycom.ownchan.activitystartmodel02-08 11:12:05.026 11356-11356/com.ownchan.activitystartmodel I/owen: onCreate method ActivityStandard taskId: 358 hasCode: 102087387902-08 11:12:05.027 11356-11356/com.ownchan.activitystartmodel I/owen: taskAffinitycom.ownchan.activitystartmodel02-08 11:12:08.113 11356-11356/com.ownchan.activitystartmodel I/owen: onCreate method ActivityStandard taskId: 358 hasCode: 52216021002-08 11:12:08.113 11356-11356/com.ownchan.activitystartmodel I/owen: taskAffinitycom.ownchan.activitystartmodel02-08 11:12:11.323 11356-11356/com.ownchan.activitystartmodel I/owen: onCreate method ActivityStandard taskId: 358 hasCode: 21376698502-08 11:12:11.324 11356-11356/com.ownchan.activitystartmodel I/owen: taskAffinitycom.ownchan.activitystartmodel

可以看到日志輸出了四次StandardActivity的和一次MainActivity的,從MainActivity進(jìn)入StandardActivity一次,后來我們又按了三次按鈕,總共四次StandardActivity的日志,并且所屬的任務(wù)棧的id都是358,這也驗(yàn)證了誰啟動(dòng)了該模式的Activity,該Activity就屬于啟動(dòng)它的Activity的任務(wù)棧中這句話,因?yàn)閱?dòng)StandardActivity的是MainActivity,而MainActivity的taskId是358,因此啟動(dòng)的StandardActivity也應(yīng)該屬于id為358的這個(gè)task,后續(xù)的3個(gè)StandardActivity是被StandardActivity這個(gè)對(duì)象啟動(dòng)的,因此也應(yīng)該還是358,所以taskId都是2087。并且每一個(gè)Activity的hashcode都是不一樣的,說明他們是不同的實(shí)例,即“每次啟動(dòng)一個(gè)Activity都會(huì)重寫創(chuàng)建一個(gè)新的實(shí)例”

singleTop-棧頂復(fù)用模式

這個(gè)模式下,如果新的activity已經(jīng)位于棧頂,那么這個(gè)Activity不會(huì)被重寫創(chuàng)建,同時(shí)它的onNewIntent方法會(huì)被調(diào)用,通過此方法的參數(shù)我們可以去除當(dāng)前請(qǐng)求的信息。如果棧頂不存在該Activity的實(shí)例,則情況與standard模式相同。需要注意的是這個(gè)Activity它的onCreate(),onStart()方法不會(huì)被調(diào)用,因?yàn)樗]有發(fā)生改變。

配置形式:

<activity android:name=".singletop.SingleTopActivity" android:launchMode="singleTop">

使用案例:

public class SingleTopActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_single_top); TextView singleTop = (TextView) findViewById(R.id.single_top); TextView other = (TextView) findViewById(R.id.single_other); singleTop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(SingleTopActivity.this, SingleTopActivity.class); startActivity(intent); } }); other.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(SingleTopActivity.this, OtherTopActivity.class); startActivity(intent); } }); }}public class OtherTopActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_other_top); TextView jump = (TextView) findViewById(R.id.jump); jump.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(OtherTopActivity.this, SingleTopActivity.class); startActivity(intent); } }); }}

輸出日志:

02-08 15:07:57.576 7635-7635/? I/owen: onCreate method MainActivity taskId: 388 hasCode: 53114957402-08 15:07:57.576 7635-7635/? I/owen: taskAffinity com.ownchan.activitystartmodel02-08 15:07:57.607 7635-7635/? I/owen: onCreate method SingleTopActivity taskId: 388 hasCode: 98506543502-08 15:07:57.607 7635-7635/? I/owen: taskAffinity com.ownchan.activitystartmodel02-08 15:08:48.270 7635-7635/com.ownchan.activitystartmodel I/owen: onNewIntent method SingleTopActivity taskId: 388 hasCode: 98506543502-08 15:08:48.271 7635-7635/com.ownchan.activitystartmodel I/owen: taskAffinity com.ownchan.activitystartmodel02-08 15:09:07.616 7635-7635/com.ownchan.activitystartmodel I/owen: onNewIntent method SingleTopActivity taskId: 388 hasCode: 98506543502-08 15:09:07.617 7635-7635/com.ownchan.activitystartmodel I/owen: taskAffinity com.ownchan.activitystartmodel02-08 15:09:28.372 7635-7635/com.ownchan.activitystartmodel I/owen: onNewIntent method SingleTopActivity taskId: 388 hasCode: 98506543502-08 15:09:28.373 7635-7635/com.ownchan.activitystartmodel I/owen: taskAffinity com.ownchan.activitystartmodel 我們看到,除了第一次進(jìn)入SingleTopActivity這個(gè)Activity時(shí),輸出的是onCreate方法中的日志,后續(xù)的都是調(diào)用了onNewIntent方法,并沒有調(diào)用onCreate方法,并且四個(gè)日志的hashcode都是一樣的,說明棧中只有一個(gè)實(shí)例。這是因?yàn)榈谝淮芜M(jìn)入的時(shí)候,棧中沒有該實(shí)例,則創(chuàng)建,后續(xù)的三次發(fā)現(xiàn)棧頂有這個(gè)實(shí)例,則直接復(fù)用,并且調(diào)用onNewIntent方法。那么假設(shè)棧中有該實(shí)例,但是該實(shí)例不在棧頂情況又如何呢? 我們先從MainActivity中進(jìn)入到SingleTopActivity,然后再跳轉(zhuǎn)到OtherActivity中,再?gòu)腛therActivity中跳回SingleTopActivity,再?gòu)腟ingleTopActivity跳到SingleTopActivity中,看看整個(gè)過程的日志。02-08 15:23:43.676 17325-17325/com.ownchan.activitystartmodel I/owen: onCreate method MainActivity taskId: 392 hasCode: 53114957402-08 15:23:43.676 17325-17325/com.ownchan.activitystartmodel I/owen: taskAffinity com.ownchan.activitystartmodel02-08 15:23:43.807 17325-17325/com.ownchan.activitystartmodel I/owen: onCreate method SingleTopActivity taskId: 392 hasCode: 68626904802-08 15:23:43.808 17325-17325/com.ownchan.activitystartmodel I/owen: taskAffinity com.ownchan.activitystartmodel02-08 15:23:53.352 17325-17325/com.ownchan.activitystartmodel I/owen: onCreate method OtherTopActivity taskId: 392 hasCode: 91577905202-08 15:23:53.353 17325-17325/com.ownchan.activitystartmodel I/owen: taskAffinity com.ownchan.activitystartmodel02-08 15:24:02.005 17325-17325/com.ownchan.activitystartmodel I/owen: onCreate method SingleTopActivity taskId: 392 hasCode: 12935108302-08 15:24:02.006 17325-17325/com.ownchan.activitystartmodel I/owen: taskAffinity com.ownchan.activitystartmodel02-08 15:24:10.284 17325-17325/com.ownchan.activitystartmodel I/owen: onNewIntent method SingleTopActivity taskId: 392 hasCode: 12935108302-08 15:24:10.285 17325-17325/com.ownchan.activitystartmodel I/owen: taskAffinity com.ownchan.activitystartmodel

我們看到從MainActivity進(jìn)入到SingleTopActivity時(shí),新建了一個(gè)SingleTopActivity對(duì)象,并且task id與MainActivity是一樣的,然后從SingleTopActivity跳到OtherActivity時(shí),新建了一個(gè)OtherActivity,此時(shí)task中存在三個(gè)Activity,從棧底到棧頂依次是MainActivity,SingleTopActivity,OtherActivity,此時(shí)如果再跳到SingleTopActivity,即使棧中已經(jīng)有SingleTopActivity實(shí)例了,但是依然會(huì)創(chuàng)建一個(gè)新的SingleTopActivity實(shí)例,這一點(diǎn)從上面的日志的hashCode可以看出,此時(shí)棧頂是SingleTopActivity,如果再跳到SingleTopActivity,就會(huì)復(fù)用棧頂?shù)腟ingleTopActivity,即會(huì)調(diào)用SingleTopActivity的onNewIntent方法。這就是上述日志的全過程。

singleTop模式分3種情況:

當(dāng)前棧中已有該Activity的實(shí)例并且該實(shí)例位于棧頂時(shí),不會(huì)新建實(shí)例,而是復(fù)用棧頂?shù)膶?shí)例,并且會(huì)將Intent對(duì)象傳入,回調(diào)onNewIntent方法 當(dāng)前棧中已有該Activity的實(shí)例但是該實(shí)例不在棧頂時(shí),其行為和standard啟動(dòng)模式一樣,依然會(huì)創(chuàng)建一個(gè)新的實(shí)例 當(dāng)前棧中不存在該Activity的實(shí)例時(shí),其行為同standard啟動(dòng)模式

standard和singleTop啟動(dòng)模式都是在原任務(wù)棧中新建Activity實(shí)例,不會(huì)啟動(dòng)新的Task,即使你指定了taskAffinity屬性。 那么什么是taskAffinity屬性呢,可以簡(jiǎn)單的理解為任務(wù)相關(guān)性。

這個(gè)參數(shù)標(biāo)識(shí)了一個(gè)Activity所需任務(wù)棧的名字,默認(rèn)情況下,所有Activity所需的任務(wù)棧的名字為應(yīng)用的包名 我們可以單獨(dú)指定每一個(gè)Activity的taskAffinity屬性覆蓋默認(rèn)值 一個(gè)任務(wù)的affinity決定于這個(gè)任務(wù)的根activity(root activity)的taskAffinity 在概念上,具有相同的affinity的activity(即設(shè)置了相同taskAffinity屬性的activity)屬于同一個(gè)任務(wù) 為一個(gè)activity的taskAffinity設(shè)置一個(gè)空字符串,表明這個(gè)activity不屬于任何task 很重要的一點(diǎn)taskAffinity屬性不對(duì)standard和singleTop模式有任何影響,即時(shí)你指定了該屬性為其他不同的值,這兩種啟動(dòng)模式下不會(huì)創(chuàng)建新的task(如果不指定即默認(rèn)值,即包名)

singleTask-棧內(nèi)復(fù)用模式

這個(gè)模式十分復(fù)雜,有各式各樣的組合。在這個(gè)模式下,如果棧中存在這個(gè)Activity的實(shí)例就會(huì)復(fù)用這個(gè)Activity,不管它是否位于棧頂,復(fù)用時(shí),會(huì)將它上面的Activity全部出棧,并且會(huì)回調(diào)該實(shí)例的onNewIntent方法。其實(shí)這個(gè)過程還存在一個(gè)任務(wù)棧的匹配,因?yàn)檫@個(gè)模式啟動(dòng)時(shí),會(huì)在自己需要的任務(wù)棧中尋找實(shí)例,這個(gè)任務(wù)棧就是通過taskAffinity屬性指定。如果這個(gè)任務(wù)棧不存在,則會(huì)創(chuàng)建這個(gè)任務(wù)棧。

配置形式:

<activity android:name=".singleTask.SingleTaskActivity" android:launchMode="singleTask" >public class SingleTaskActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_single_top); TextView singleTop = (TextView) findViewById(R.id.single_top); TextView other = (TextView) findViewById(R.id.single_other); singleTop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(SingleTaskActivity.this, SingleTaskActivity.class); startActivity(intent); } }); other.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(SingleTaskActivity.this, OtherTaskActivity.class); startActivity(intent); } }); }}public class OtherTaskActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_other_top); TextView jump = (TextView) findViewById(R.id.jump); jump.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(OtherTaskActivity.this, SingleTaskActivity.class); startActivity(intent); } }); }}

現(xiàn)在我們先不指定任何taskAffinity屬性,對(duì)它做類似singleTop的操作,即從入口MainActivity進(jìn)入SingleTaskActivity,然后跳到OtherActivity,再跳回到SingleTaskActivity。看看整個(gè)過程的日志。

02-08 15:56:07.446 4787-4787/com.ownchan.activitystartmodel I/owen: onCreate method MainActivity taskId: 397 hasCode: 53114957402-08 15:56:07.446 4787-4787/com.ownchan.activitystartmodel I/owen: taskAffinity com.ownchan.activitystartmodel02-08 15:56:07.568 4787-4787/com.ownchan.activitystartmodel I/owen: onCreate method SingleTaskActivity taskId: 397 hasCode: 98506543502-08 15:56:07.568 4787-4787/com.ownchan.activitystartmodel I/owen: taskAffinity com.ownchan.activitystartmodel02-08 15:56:22.997 4787-4787/com.ownchan.activitystartmodel I/owen: onNewIntent method SingleTaskActivity taskId: 397 hasCode: 98506543502-08 15:56:22.997 4787-4787/com.ownchan.activitystartmodel I/owen: taskAffinity com.ownchan.activitystartmodel02-08 15:56:28.876 4787-4787/com.ownchan.activitystartmodel I/owen: onCreate method OtherTaskActivity taskId: 397 hasCode: 6244982302-08 15:56:28.876 4787-4787/com.ownchan.activitystartmodel I/owen: taskAffinity com.ownchan.activitystartmodel02-08 15:56:32.439 4787-4787/com.ownchan.activitystartmodel I/owen: onNewIntent method SingleTaskActivity taskId: 397 hasCode: 98506543502-08 15:56:32.439 4787-4787/com.ownchan.activitystartmodel I/owen: taskAffinity com.ownchan.activitystartmodel

當(dāng)我們從MainActiviyty進(jìn)入到SingleTaskActivity,再進(jìn)入到OtherActivity后,此時(shí)棧中有3個(gè)Activity實(shí)例,并且SingleTaskActivity不在棧頂,而在OtherActivity跳到SingleTaskActivity時(shí),并沒有創(chuàng)建一個(gè)新的SingleTaskActivity,而是復(fù)用了該實(shí)例,并且回調(diào)了onNewIntent方法。并且原來的OtherActivity出棧了,具體見下面的信息,使用命令adb shell dumpsys activity activities可進(jìn)行查看

如果不存在,則會(huì)創(chuàng)建一個(gè)新的Task,并創(chuàng)建新的Activity實(shí)例入棧到新創(chuàng)建的Task中去 如果存在,則得到該任務(wù)棧,查找該任務(wù)棧中是否存在該Activity實(shí)例 如果存在實(shí)例,則將它上面的Activity實(shí)例都出棧,然后回調(diào)啟動(dòng)的Activity實(shí)例的onNewIntent方法 如果不存在該實(shí)例,則新建Activity,并入棧

singleInstance-全局唯一模式

該模式具備singleTask模式的所有特性外,與它的區(qū)別就是,這種模式下的Activity會(huì)單獨(dú)占用一個(gè)Task棧,具有全局唯一性,即整個(gè)系統(tǒng)中就這么一個(gè)實(shí)例,由于棧內(nèi)復(fù)用的特性,后續(xù)的請(qǐng)求均不會(huì)創(chuàng)建新的Activity實(shí)例,除非這個(gè)特殊的任務(wù)棧被銷毀了。以singleInstance模式啟動(dòng)的Activity在整個(gè)系統(tǒng)中是單例的,如果在啟動(dòng)這樣的Activiyt時(shí),已經(jīng)存在了一個(gè)實(shí)例,那么會(huì)把它所在的任務(wù)調(diào)度到前臺(tái),重用這個(gè)實(shí)例。<activity android:name=".singleinstance.SingleInstanceActivity" android:launchMode="singleInstance" >public class ActivitySingleInstance extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_singleinstance); }}配置屬性如下:<activity android:name=".ActivitySingleInstance" android:launchMode="singleInstance"> <intent-filter> <action android:name="com.castiel.demo.singleinstance" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter></activity>

使用下面的方式分別在兩個(gè)應(yīng)用中啟動(dòng)它

Intent intent = new Intent();intent.setAction("com.castiel.demo.singleinstance");startActivity(intent);

我們看到,第一個(gè)應(yīng)用啟動(dòng)SingleInstanceActivity時(shí),由于系統(tǒng)中不存在該實(shí)例,所以新建了一個(gè)Task,按home鍵后,使用另一個(gè)App進(jìn)入該Activity,由于系統(tǒng)中已經(jīng)存在了一個(gè)實(shí)例,不會(huì)再創(chuàng)建新的Task,直接復(fù)用該實(shí)例,并且回調(diào)onNewIntent方法。可以從他們的hashcode中可以看出這是同一個(gè)實(shí)例。因此我們可以理解為:SingleInstance模式啟動(dòng)的Activity在系統(tǒng)中具有全局唯一性。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 巴楚县| 江源县| 嘉荫县| 长海县| 苏尼特右旗| 柏乡县| 什邡市| 芜湖市| 赤水市| 长寿区| 恩施市| 枣阳市| 新巴尔虎右旗| 清远市| 阿瓦提县| 闻喜县| 荆州市| 那曲县| 宾阳县| 华亭县| 盈江县| 麦盖提县| 郁南县| 庆元县| 观塘区| 关岭| 江源县| 贺州市| 望城县| 额尔古纳市| 昆明市| 门头沟区| 岚皋县| 双桥区| 肥城市| 丁青县| 凤冈县| 依兰县| 双城市| 乌拉特前旗| 宕昌县|