1. 什么是Activity
- Activity負責UI元素的加載與頁面之前的跳轉(zhuǎn)箍邮,代表了一個頁面單元。
2. Activity的構(gòu)成
- Activity的構(gòu)成并不是一個Activity對象再加上一個布局那么簡單叨叙,在Activity和開發(fā)人員設置的視圖之間還隔著兩層锭弊。
- 實際上視圖會被設置給一個Window類,這個Window中含有一個DecorView擂错,這個DecorView才是整個窗口的頂級視圖味滞。開發(fā)人員設置的布局會被設置到這個DecorView的mContentParent布局中。
- 也就是說Android中實際上內(nèi)置了一些系統(tǒng)布局文件xml钮呀,我們在xml中定義的視圖最終會被設置到這些系統(tǒng)布局的特定節(jié)點之下剑鞍,這樣就形成了整個的DecorView。
3. 隱式啟動Activity
顯式Intent指的是Intent的“意圖”非常明顯爽醋,指明了從哪個活動跳轉(zhuǎn)到哪個活動蚁署。隱式Intent并不明確指出啟動哪一個活動,而是指定一系列更為抽象的action和category信息子房,然后交由系統(tǒng)去分析這個intent形用,并幫我們找到合適的活動去啟動就轧。
默認的category的intent
- 創(chuàng)建FirstActivity,并且在配置文件中配置action和category:
public class FirstActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/bt_first"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="I am FirstActivity"
android:textSize="50px" />
</LinearLayout>
<activity android:name=".FirstActivity">
<intent-filter>
<action android:name="com.fkq.menu.First" />
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
說明:
- 在<action>標簽中我們指明了當前活動可以響應 com.fkq.menu.First 這個action田度,而<category>標簽則包含一些附加信息妒御,更精確地指明了當前的活動能夠響應的Intent中還可能帶有的category。
- 只有<action>和<category>中的內(nèi)容同時能夠匹配上Intent指定的action和category時镇饺,這個活動才能響應該Intent乎莉。
2.修改MainActivity,進行跳轉(zhuǎn):
@InjectView(R.id.bt_main)
Button btMain;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
btMain.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.bt_main:
startActivity(new Intent("com.fkq.menu.First"));
}
}
});
}
說明:android.intent.category.DEFAULT 是默認的category奸笤,在調(diào)用startActivity方法的時候會自動將這個category添加到Intent中惋啃。
- 非默認的category的intent
每個Intent中只能指定一個action,但卻能指定多個category监右。
1.修改配置文件的category边灭,即添加一個:
<activity android:name=".FirstActivity">
<intent-filter>
<action android:name="com.fkq.menu.First" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="com.fkq.menu.my_category"/>
</intent-filter>
</activity>
2.修改MainActivity的startActivity部分代碼:
Intent intent = new Intent("com.fkq.menu.First");
intent.addCategory("com.fkq.menu.my_category");
startActivity(intent);
4. 更多Intent用法
1. 簡單示例
使用隱式Intent,不僅可以啟動自己程序內(nèi)的活動健盒,還可以啟動其他程序的活動绒瘦,這使得Android多個應用程序之間的功能共享成為了可能。
比如應用程序中需要展示一個網(wǎng)頁扣癣,只需要調(diào)用系統(tǒng)的瀏覽器來打開這個網(wǎng)頁即可惰帽。
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
說明:
- 首先指定了Intent的action是Intent.ACTION_ViEW,這是一個Android系統(tǒng)內(nèi)置的動作,其常量值為android.intent.action.VIEW.
- 然后通過Uri.parse方法父虑,將一個網(wǎng)址字符串解析承一個Uri對象该酗。
- 再調(diào)用Intent的setData方法將這個Uri對象傳遞進去。
再次說明:
setData方法接收一個Uri對象士嚎,主要用于指定當前Intent正在操作的數(shù)據(jù)呜魄,而這些數(shù)據(jù)通常都是以字符串的形式傳入到Uri.parse方法中解析產(chǎn)生的。
2. 配置data標簽
我們可以在<intent-filter>標簽中再配置一個<data>標簽莱衩,用于更精確地指定當前活動能夠響應什么類型的數(shù)據(jù)耕赘。<data>標簽中主要可以配置以下內(nèi)容:
- android:scheme 用于指定數(shù)據(jù)的協(xié)議部分,如上例中的http部分膳殷。
- android:host 用于指定數(shù)據(jù)的主機名部分,如上例中的www.baidu.com部分九火。
- android:port 用于指定數(shù)據(jù)的端口部分赚窃,一般緊跟在主機名之后。
- android:path 用于指定主機名和端口之后的部分岔激,如一段網(wǎng)址中跟在域名之后的內(nèi)容勒极。
- android:mimeType 用于指定可以處理的數(shù)據(jù)類型,允許使用通配符的方式進行指定虑鼎。
注意:只有<data>標簽中指定的內(nèi)容和Intent中攜帶的Data完全一致時辱匿,當前活動才能夠響應該Intent键痛。不過一般在<data>標簽中都不會指定過多的內(nèi)容,如上面瀏覽器示例中匾七,其實只需要指定android:scheme為http絮短,就可以響應所有的http協(xié)議的Intent了。
修改配置文件如下:
<activity android:name=".FirstActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" />
</intent-filter>
</activity>
說明:<data>標簽中通過android:sheme指定了數(shù)據(jù)的協(xié)議必須是http協(xié)議昨忆,這樣就和瀏覽器一樣丁频,能夠響應一個打開網(wǎng)頁的Intent了。
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
除了http協(xié)議外邑贴,我們還可以指定很多其他協(xié)議席里,比如geo表示顯示地理位置、tel表示撥打電話拢驾。
<intent-filter>
<action android:name="android.intent.action.DIAL" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="tel" />
</intent-filter>
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
說明:
- 首先指定Intent的action是Intent.ACTION_DIAL,這又是Android系統(tǒng)的內(nèi)置動作奖磁。
- 然后在data部分指定了協(xié)議是tel,號碼是10086繁疤。
5. 向下一個活動傳遞數(shù)據(jù)
發(fā)送:
String data = "hello world";
Intent intent = new Intent(MainActivity.this,FirstActivity.class);
intent.putExtra("mydata",data);
startActivity(intent);
說明:通過putExtra方法傳遞一個字符串咖为,接收兩個參數(shù),第一個參數(shù)是鍵嵌洼,用于從Intent中取值案疲,第二個參數(shù)才是真正要傳遞的數(shù)據(jù)。
接收:
Intent intent = getIntent();
String data = intent.getStringExtra("mydata");
Toast.makeText(this, "傳遞過來的值是" + data, Toast.LENGTH_SHORT).show();
說明:通過getIntent方法獲取到用于啟動FirstActivity的Intent麻养,然后調(diào)用getStringExtra方法來獲取傳遞的數(shù)據(jù)褐啡。如果是整型數(shù)據(jù),則使用getIntExtra方法鳖昌,如果是布爾數(shù)據(jù)备畦,則使用getBooleanExtra方法。
6. 返回數(shù)據(jù)給上一個活動
Activity中有一個startActivityForResult方法用于啟動活動许昨,期望在活動銷毀的時候能夠返回一個結(jié)果給上一個活動懂盐。
- 示例:MainActivity跳轉(zhuǎn)到FirstActivity,F(xiàn)irstActivity銷毀返回數(shù)據(jù)給MainActivity
MainActivity:
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.bt_trans:
Intent intent = new Intent(MainActivity.this, FirstActivity.class);
startActivityForResult(intent, 1);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode){
case 1:
if (resultCode == RESULT_OK){
String returnedData = data.getStringExtra("data_return");
Log.e("MainActivity",returnedData);
}
}
}
說明:
- startActivityForResult方法接收兩個參數(shù)糕档,第一個參數(shù)還是intent莉恼,第二個參數(shù)是請求碼,用于在之后的回調(diào)中判斷數(shù)據(jù)的來源速那。
- 使用startActivityForResult方法啟動SecondActivity俐银,請求碼只要是唯一值就可以了,這里傳入了1端仰。
FirstActivity:
Button button = (Button) findViewById(R.id.bt_re_data);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.bt_re_data:
Intent intent = new Intent();
intent.putExtra("data_return","hello");
setResult(RESULT_OK,intent);
finish();
break;
}
}
});
說明:
- 在FirstActivity里面給按鈕添加點擊事件捶惜,并添加返回數(shù)據(jù)的邏輯。
- 構(gòu)建一個Intent僅僅用于傳遞數(shù)據(jù)而已荔烧,緊接著把要傳遞的數(shù)據(jù)存放在Intent中吱七,然后調(diào)用setResult方法汽久,專門用于向上一個活動返回數(shù)據(jù)的。
- setResult方法接收兩個參數(shù)踊餐,第一個參數(shù)用于向上一個活動返回處理結(jié)果景醇,一般只使用RESULT_OK或RESULT_CANCELED這兩個值,第二個參數(shù)則把帶有數(shù)據(jù)的intent傳遞回去市袖,然后調(diào)用finish方法銷毀當前活動秀睛。
- 由于使用startActivityForResult方法來啟動FirstActivity的甥捺,在FirstActivity被銷毀之后會回調(diào)MainActivity的onActivityResult方法,因此我們需要在MainActivity中重寫這個方法來得到返回的數(shù)據(jù)。
- onActivityResult方法帶有三個參數(shù)肃续,第一個參數(shù)requestCode孵奶,就是啟動活動的時候傳入的請求碼伙狐。第二個參數(shù)resultCode氓奈,就是我們在返回數(shù)據(jù)時傳入的處理結(jié)果。第三個參數(shù)data蜓肆,就是攜帶著返回數(shù)據(jù)的Intent颜凯。
- 由于一個活動中可能調(diào)用startActivityForResult方法去啟動很多不同的活動,每一個活動返回的數(shù)據(jù)都會回調(diào)到onActivityResult這個方法中仗扬,因此首先要做得就是檢查requestCode的值來判斷數(shù)據(jù)來源症概。確定數(shù)據(jù)是從FirstActivity返回的之后,再通過resultCode的值來判斷處理結(jié)果是否成功早芭。最后從data中取值并打印出來彼城,這樣就完成了向上一個活動返回數(shù)據(jù)的工作。
疑問:
假如FirstActivity中不用按鈕來銷毀活動退个,而是通過點擊Back鍵募壕,那如何處理呢?很簡單:在FirstActivity中重寫onBackPressed方法來解決這個問題语盈。
@Override
public void onBackPressed() {
Intent intent = new Intent();
intent.putExtra("data_return","hello");
setResult(RESULT_OK,intent);
finish();
}
7. 活動的生命周期
返回棧
Android是用任務(Task)來管理活動的舱馅,一個任務就是一組存放在棧里的活動的集合,這個棧也被稱作返回棧刀荒。
每當我們啟動一個新的活動代嗤,它會在返回棧中入棧,并處于棧頂?shù)奈恢貌琛C慨斘覀儼聪翨ack鍵或調(diào)用finish方法去銷毀一個活動時资溃,處于棧頂?shù)幕顒訒鰲#@時前一個入棧的活動就會重新處于棧頂?shù)奈恢谩?/p>
系統(tǒng)總是會顯示處于棧頂?shù)幕顒咏o用戶烈炭。
活動狀態(tài)
- 運行狀態(tài):當一個活動處于棧頂時,這個活動就處于運行狀態(tài)宝恶。
- 暫停狀態(tài):當一個活動不處于棧頂符隙,但是依然可見的時候趴捅,這個活動就進入了暫停狀態(tài)。如:對話框后面的活動霹疫。
- 停止狀態(tài):當一個活動不處于棧頂拱绑,并且完全不可見的時候,就進入了停止狀態(tài)丽蝎。系統(tǒng)仍然會為這種活動保存相應的狀態(tài)和成員變量猎拨。當其他地方需要內(nèi)存時,活動可能會被系統(tǒng)回收屠阻。
- 銷毀狀態(tài):當一個活動從返回棧中移除后就變成了銷毀狀態(tài)红省。
- 由于可見的活動被回收,用戶體驗不好国觉,所以系統(tǒng)最不愿意回收運行和暫停狀態(tài)的活動吧恃,當內(nèi)存緊張的時候,會優(yōu)先回收銷毀狀態(tài)和停止狀態(tài)的活動麻诀。
活動的生存期
- Activity類中定義了7個回調(diào)方法痕寓,覆蓋了活動生命周期的每一個環(huán)節(jié):
- onCreate:
活動第一次被創(chuàng)建的時候調(diào)用,所以在這個活動中完成初始化操作:加載布局蝇闭,綁定事件等呻率。 - onStart:
活動由不可見變?yōu)榭梢姷臅r候調(diào)用。 - onResume:
活動準備好和用戶進行交互的時候調(diào)用呻引。 - onPause:
這個活動在系統(tǒng)準備去啟動或者恢復另一個活動的時候調(diào)用礼仗。通常會在這個方法中將一些消耗CPU的資源釋放掉,以及保存一些關(guān)鍵數(shù)據(jù)苞七,但是這個活動執(zhí)行速度一定要快藐守,不然會影響新的棧頂活動的使用。 - onStop:
這個方法在活動完全不可見的時候調(diào)用蹂风。與onPause方法主要區(qū)別是:如果啟動的新活動是一個對話框式的活動卢厂,那么onPause方法會得到執(zhí)行,而onStop方法并不會惠啄。
當活動執(zhí)行了onStop方法慎恒,此時另一個優(yōu)先級更高的程序需要內(nèi)存,可能會殺掉進程撵渡,這時再啟動的話融柬,會先執(zhí)行onCreate方法。 - onDestory:
活動被銷毀前調(diào)用趋距。 - onRestart:
活動由停止狀態(tài)變?yōu)檫\行狀態(tài)之前調(diào)用粒氧,即重新啟動時調(diào)用,意思就是當一個活動執(zhí)行了onStop方法节腐,但是并沒有執(zhí)行onDestory方法時外盯,如果被重新啟動摘盆,會執(zhí)行onRestart方法,然后會執(zhí)行onStart方法饱苟,而不會重新執(zhí)行onCreate方法孩擂。
- 以上活動又分為3種生存期
- 完整生存期:活動在onCreate方法和onDestroy方法之間所經(jīng)歷的,就是完整生存期箱熬。
- 可見生存期:活動在onStart和onStop方法之間所經(jīng)歷的类垦,就是可見生存期。在這個生存期內(nèi)城须,onStart方法對資源進行加載蚤认,而在onStop方法對資源進行釋放,合理管理對用戶可見的資源酿傍。
- 前臺生存期:活動在onResume方法和onPause方法之間就是前臺生存期烙懦。
體驗活動的生命周期
1.創(chuàng)建MainActivity:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
setContentView(R.layout.activity_main);
Button startNormalActivity = (Button) findViewById(R.id.start_normal_activity);
Button startDialogActivity = (Button) findViewById(R.id.start_dialog_activity);
startNormalActivity.setOnClickListener(this);
startDialogActivity.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.start_normal_activity:
startActivity(new Intent(this, NormalActivity.class));
break;
case R.id.start_dialog_activity:
startActivity(new Intent(this, DialogActivity.class));
break;
}
}
@Override
protected void onStart() {
super.onStart();
Log.d(TAG, "onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume");
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause");
}
@Override
protected void onStop() {
super.onStop();
Log.d(TAG, "onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(TAG, "onRestart");
}
}
2.創(chuàng)建DialogActivity和NormalActivity:
public class DialogActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dialog);
}
}
public class NormalActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_normal);
}
}
3.修改配置文件:
<activity android:name=".NormalActivity"></activity>
<activity
android:name=".DialogActivity"
android:theme="@style/Theme.AppCompat.Dialog">
</activity>
注意:由于類繼承的是AppCompatActivity,所以主題應該是AppCompat里面的赤炒,否則會報錯氯析。
說明:針對MainActivity
- 進入應用程序,MainActivity第一次被創(chuàng)建會依次執(zhí)行onCreate莺褒、onStart掩缓、onResume方法
- 啟動NormalActivity,MainActivity會執(zhí)行onPause和onStop方法遵岩,因為NormalActivity把MainActivity完全遮掩住了你辣。
- 按下Back返回MainActivity,MainActivity會執(zhí)行onRestart方法尘执,然后執(zhí)行onStart和onResume方法舍哄,因為之前MainActivity已經(jīng)進入了停止狀態(tài),所以onRestart方法誊锭;之所以onCreate方法沒有執(zhí)行表悬,因為MainActvity并沒有重新創(chuàng)建。
- 啟動DialogActivity丧靡,MainActivity只會執(zhí)行onPause方法蟆沫,onStop方法并沒有執(zhí)行,因為DialogActivity并沒有完全遮掩住MainActivity温治,MainActivity只是進入了暫停狀態(tài)饭庞,并沒有進入停止狀態(tài)。相應地熬荆,按下Back鍵返回MainActivity也應該只有onResume方法會得到執(zhí)行舟山。
- 在MainActivty頁面按下Back鍵推出程序,依次執(zhí)行onPause、onStop捏顺、onDestory方法六孵。
8. 活動被回收了怎么辦
當活動被銷毀以后,可能會銷毀掉活動中原有的數(shù)據(jù)幅骄,比如EditText中輸入的內(nèi)容。為了解決這個問題本今,Android提供了一個onSaveInstanceState回調(diào)方法拆座,這個方法可以保證在活動被回收之前一定會被調(diào)用。
onSaveInstanceState方法會攜帶一個Bundle類型的參數(shù)冠息,Bundle提供了一系列的方法用于保存數(shù)據(jù)挪凑,比如可以使用putString保存字符串,使用putInt方法保存整形數(shù)據(jù)逛艰,以此類推躏碳。每個保存方法需要傳入兩個參數(shù),第一個參數(shù)是鍵散怖,用于后面從Bundle中取值菇绵,第二個參數(shù)是真正要保存的內(nèi)容。
@Override
public void onSaveInstanceState(Bundle outState) {
String tempdata = "something you just typed";
outState.putString("data_key",tempdata);
super.onSaveInstanceState(outState);
Log.e(TAG,"此時被調(diào)用");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState!=null){
String tempdata = savedInstanceState.getString("data_key");
Toast.makeText(this,"tempdata::"+tempdata,Toast.LENGTH_SHORT).show();
}
}
說明:
- 利用手機的橫豎屏切換镇眷,可以完美做模擬咬最,先調(diào)用onSaveInstanceState,然后調(diào)用onCreate欠动。
- onCreate方法中有一個Bundle類型的參數(shù)永乌。這個參數(shù)在一般情況下都是null,但是如果在活動被系統(tǒng)回收之前有通過onSaveInstanceState方法來保存數(shù)據(jù)的話具伍,這個參數(shù)就會帶有之前所保存的全部數(shù)據(jù)翅雏。
9. 活動的啟動模式和應用場景
啟動模式有4種,分別是standard人芽、singleTop望几、singleTask和singleInstance,可以在配置文件中通過給<activity>標簽指定android:launchMode屬性來選擇啟動模式啼肩。
standard
不管活動是否已經(jīng)在返回棧中存在橄妆,每次啟動都會創(chuàng)建一個新的實例,并且位于棧頂祈坠。
singleTop
在啟動活動時如果發(fā)現(xiàn)返回棧的棧頂已經(jīng)是該活動害碾,則認為可以直接使用它,不會再創(chuàng)建新的活動實例赦拘。
應用場景:下拉欄通知界面點擊進入一個頁面的情景慌随,避免了因為多次啟動導致的需要返回多次的情況。
singleTask
每次啟動該活動時系統(tǒng)首先會在返回棧中檢查是否存在該活動的實例,如果發(fā)現(xiàn)已經(jīng)存在則直接使用該實例,并把在這個活動之上的所有活動統(tǒng)統(tǒng)出棧阁猜,如果沒有發(fā)現(xiàn)就會創(chuàng)建一個新的活動示例丸逸。
應用場景: 例如瀏覽器的主界面。不管從多少個應用啟動瀏覽器剃袍,只會啟動主界面一次黄刚,其余情況都會走onNewIntent,并且會清空主界面上面的其他頁面民效。之前打開過的頁面憔维,打開之前的頁面就ok,不再新建.
singleInstance
啟動一個新的返回棧來管理這個活動畏邢。假設我們的程序中有一個活動是允許其他程序調(diào)用的业扒,如果我們想實現(xiàn)其他程序和我們的程序可以共享這個活動的案例,使用之前的三種模式是做不到的舒萎,因為每個應用程序都有自己的返回棧程储,同一個活動在不同的返回棧中入棧時必然是創(chuàng)建了新的實例。而使用singleInstance模式就可以解決這個問題臂寝,在這個種模式下會有一個單獨的返回棧來管理活動章鲤,不管是哪個應用程序來訪問這個活動,都共用同一個返回棧交煞,也就解決了共享活動實例的問題咏窿。
栗子:FirstActivity跳轉(zhuǎn)到SecondActivity,然后在SecondActivity進入到THirdActivity素征。SecondActivity單獨在一個返回棧集嵌,F(xiàn)irstActivity和THirdActivity在一個返回棧。點擊Back御毅,ThirdActivity直接返回到FirstActivity根欧,再按下Back鍵又會返回到SecondActivity,再按下Back鍵會推出程序端蛆。
原理:FirstA和ThridA存放在同一個返回棧凤粗,當在ThridA的界面按下Back鍵,ThridAcitivy會從返回棧出棧今豆,F(xiàn)irstA成為棧頂活動顯示在界面上嫌拣。在FirstA界面上按下Back鍵,當前的返回棿舳悖空了就顯示了另一個返回棧的棧頂活動异逐,即SecondActivity,按下Back插掂,所有的返回椈艺埃空了腥例,退出程序。
應用場景: 比如通話頁面酝润、鬧鈴提醒頁面.
10. 動態(tài)設置活動的啟動模式
- FLAG_ACTIVITY_NEW_TASK
舉例說明:經(jīng)過測試燎竖,并沒有開啟一個額外的任務棧,并且會重新創(chuàng)建要销。(如果測試不正確构回,后期會修改)
- FLAG_ACTIVITY_SINGLE_TOP
舉例說明:棧中有A B C D四個活動,在D中用這個Flag啟動D疏咐,現(xiàn)在棧中有A B C D 四個活動捐凭,D不會重新創(chuàng)建,會回調(diào)onNewIntent方法凳鬓。
- FLAG_ACTIVITY_CLEAR_TOP
舉例說明:棧中有A B C D 四個活動,在D中用這個Flag啟動B患民,此時棧中只有A B ,B會重新創(chuàng)建缩举。
- FLAG_ACTIVITY_NO_HISTORY
舉例說明:棧中有A B C D 四個活動,在D中用這個Flag啟動B匹颤,B會重新創(chuàng)建仅孩,此時棧中有A B C D 新B,然后從新B打開C,現(xiàn)在棧中有A B C D C 五個活動印蓖。
- FLAG_ACTIVITY_BROUGHT_TO-FRONT
舉例說明:我們有A,A打開B,B打開C,C打開D,D然后以這個Flag啟動B, 此時棧的情況就是A,C,D,B辽慕。B不會重新創(chuàng)建,回調(diào)onNewIntent方法赦肃。
- FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_NEW_TASK
舉例說明: 我看郭霖博客溅蛉,這兩個Flag可以讓Activity不會重新創(chuàng)建,但是經(jīng)過我測試他宛,依然會重新創(chuàng)建船侧。(如果測試不正確,后期會修改)
11. 知曉當前是在哪一個活動
創(chuàng)建BaseActivity厅各,讓FirstActivity镜撩、SecondActivity、ThirdActivity繼承BaseAcitify队塘,點擊進入FirstActivity袁梗、SecondActivity、ThirdActivity憔古,Log就會打印出當前活動的名稱遮怜。BaseActivity代碼如下:
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("BaseActivity",getClass().getSimpleName());
}
}
12.隨時隨地退出程序
- 新建ActivityCollector:
public class ActivityCollector {
public static List<Activity> activities = new ArrayList<>();
public static void addActivity(Activity activity) {
activities.add(activity);
}
public static void removeActivity(Activity activity) {
activities.remove(activity);
}
public static void finishAll() {
for (Activity activity : activities) {
if (!activity.isFinishing()) {
activity.finish();
}
}
}
}
2.新建BaseActivity:
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("BaseActivity",getClass().getSimpleName());
ActivityCollector.addActivity(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
ActivityCollector.removeActivity(this);
}
}
3.新建FirstActivity繼承BaseActivity:
ActivityCollector.finishAll();
android.os.Process.killProcess(android.os.Process.myPid());
說明:
- FirstActivity繼承BaseActivity,啟動FirstActivity投放,F(xiàn)irstActivity這個類就會被保存到集合里面奈泪。
- 如果FirstActivit被系統(tǒng)內(nèi)存回收銷毀后,集合會把FirstActivit移除。
- 想退出程序涝桅,只需清空集合即可拜姿。
- 為了保證程序完全退出,殺掉當前進程:killProcess方法用于殺掉一個進程冯遂,它接收一個進程id參數(shù)蕊肥,我們可以通過myPid()方法來獲得當前程序的進程id。
13. 啟動活動的最佳寫法
假設SecondActivity中需要用到兩個非常重要的字符串參數(shù)蛤肌,在啟動MainActivity的時候必須要傳遞過來:
Intent intent = new Intent(this,MainActivity.class);
intent.putExtra("param1","data1");
intent.putExtra("param2","data2");
startActivity(intent);
public static void actionStart(Context context, String data1, String data2) {
Intent intent = new Intent(context, SecondActivity.class);
intent.putExtra("param1", data1);
intent.putExtra("param2", data2);
context.startActivity(intent);
}
MainActivity.actionStart(this,"data1","data2");