返回棧
- android中的活動(dòng)是可以層疊的,每啟動(dòng)一個(gè)活動(dòng)嘱能,就會(huì)覆蓋在原活動(dòng)之上妓湘,然后點(diǎn)擊Back鍵會(huì)銷毀坐上面的活動(dòng)歉嗓,下面的一個(gè)活動(dòng)就會(huì)重新的顯示出來(lái)
- 其實(shí)Android是使用任務(wù)來(lái)管理活動(dòng)的鞍历,一個(gè)任務(wù)就是一組存放在棧里的活動(dòng)集合舵抹,這個(gè)棧也被稱之為返回棧,棧是一種后進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)劣砍,在默認(rèn)情況下惧蛹,每當(dāng)我們啟動(dòng)了一個(gè)新的活動(dòng),它就會(huì)返回棧中入棧秆剪,并且處于棧頂?shù)奈恢茫慨?dāng)我們按下Back鍵或者調(diào)用finish()方法去銷毀一個(gè)活動(dòng)的時(shí)候爵政,返回棧頂?shù)幕顒?dòng)會(huì)出棧仅讽,這時(shí)前一個(gè)入棧的活動(dòng)就會(huì)重新處于棧頂?shù)奈恢茫到y(tǒng)總是會(huì)顯示處于棧頂?shù)幕顒?dòng)給用戶
活動(dòng)狀態(tài)
每個(gè)活動(dòng)在其生命周期中最多可能會(huì)有四個(gè)狀態(tài)
- 運(yùn)行狀態(tài)
- 當(dāng)一個(gè)活動(dòng)位于返回棧的棧頂?shù)臅r(shí)候钾挟,這個(gè)活動(dòng)就處于運(yùn)行狀態(tài)
- 暫定狀態(tài)
- 當(dāng)一個(gè)活動(dòng)不再處于棧頂位置的時(shí)候洁灵,但是仍然是可見(jiàn),這個(gè)活動(dòng)進(jìn)進(jìn)入了暫停狀態(tài)掺出,比如對(duì)話框形式的活動(dòng)只會(huì)占用屏幕中間的區(qū)域徽千,處于暫停狀態(tài)的活動(dòng)仍然是完全存活
- 停止?fàn)顟B(tài)
- 當(dāng)一個(gè)活動(dòng)不再處于棧頂位置,并且完全不可見(jiàn)的時(shí)候汤锨,就會(huì)進(jìn)入停止的狀態(tài)双抽,這個(gè)時(shí)候活動(dòng)相應(yīng)的狀態(tài)和成員變量會(huì)當(dāng)系統(tǒng)內(nèi)存不夠的時(shí)候隨時(shí)被回收
- 銷毀狀態(tài)
- 當(dāng)一個(gè)活動(dòng)從返回棧中移除后就會(huì)變成銷毀的狀態(tài)
活動(dòng)的生存期
Activity類定義了七個(gè)回調(diào)方法,覆蓋了活動(dòng)生命周期的每一個(gè)環(huán)節(jié)
- onCreate()
- 這個(gè)方法會(huì)在活動(dòng)第一個(gè)被創(chuàng)建的時(shí)候調(diào)用闲礼,比如加載布局牍汹,綁定事件
- onStart()
- 這個(gè)方法在活動(dòng)由不可見(jiàn)變?yōu)榭梢?jiàn)的時(shí)候調(diào)用
- onResume()
- 這個(gè)方法在活動(dòng)準(zhǔn)備好和用戶進(jìn)行交互的時(shí)候調(diào)用铐维,此時(shí)的活動(dòng)一定位于返回棧的棧頂,并且處于運(yùn)行的狀態(tài)
- onPause()
- 這個(gè)方法在系統(tǒng)準(zhǔn)備啟動(dòng)或者恢復(fù)另一個(gè)活動(dòng)的時(shí)候調(diào)用慎菲,通常會(huì)在這個(gè)方法中將一些消耗CPU的資源釋放掉嫁蛇,以及保存一些關(guān)鍵數(shù)據(jù),這個(gè)方法執(zhí)行速度一定要快露该,不然會(huì)影響新的棧頂活動(dòng)的使用
- onStop()
- 這個(gè)方法在活動(dòng)完全不可見(jiàn)的時(shí)候調(diào)用睬棚,他和onPause()方法的主要區(qū)別就是,如果啟動(dòng)的新活動(dòng)是一個(gè)對(duì)話框的活動(dòng)那個(gè)解幼,那么onPause()方法會(huì)執(zhí)行抑党,onStop()方法不會(huì)執(zhí)行
- onDestroy()
- 這個(gè)方法在活動(dòng)被銷毀之前帶哦用,之后活動(dòng)的狀態(tài)將變?yōu)殇N毀狀態(tài)
- onRestart()
- 這個(gè)方法在活動(dòng)由停止?fàn)顟B(tài)變?yōu)檫\(yùn)行狀態(tài)之前用书幕,也就是活動(dòng)被重新的啟動(dòng)
這七個(gè)方法是兩兩相對(duì)的新荤,除了onRestart()
- 這個(gè)方法在活動(dòng)由停止?fàn)顟B(tài)變?yōu)檫\(yùn)行狀態(tài)之前用书幕,也就是活動(dòng)被重新的啟動(dòng)
-
完整生存期
活動(dòng)在onCreate()和onDrstroy()方法之間所經(jīng)歷的,就是完整生存期台汇,在第一個(gè)方法中完成各種初始化的操作苛骨,在onDestroy()中完成釋放內(nèi)存的操作 -
可見(jiàn)生存器
活動(dòng)在onStart()和onStop()方法之間所經(jīng)歷,在這個(gè)時(shí)期苟呐,活動(dòng)對(duì)于用戶是可見(jiàn)的痒芝,即便有可能無(wú)法與用戶進(jìn)行交互,可以通過(guò)這兩個(gè)方法牵素,合理管理用戶可見(jiàn)的資源严衬,從而保證處于停止?fàn)顟B(tài)的活動(dòng)不會(huì)占用過(guò)多的內(nèi)存 -
前臺(tái)生存期
活動(dòng)在onResume()方法和onPause()方法之間所經(jīng)歷的就是前臺(tái)生存器,在前臺(tái)生存期笆呆,活動(dòng)總是處于運(yùn)行的狀態(tài)请琳,此時(shí)的活動(dòng)是可以和用戶進(jìn)行交互的,看到最多的時(shí)期就是這個(gè)狀態(tài)下的活動(dòng)
體驗(yàn)活動(dòng)的生命周期
創(chuàng)建項(xiàng)目
- 在activity_mian2.xml中
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="@+id/text_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="我是第一個(gè)"
android:textSize="30sp" />
</LinearLayout>
- 在activity_mian3.xml中
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="@+id/text_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="我是第二個(gè)"/>
</LinearLayout>
- 這兩個(gè)代碼基本差不多赠幕,對(duì)應(yīng)的Main2Activity和Main3Activity不用改
- 開(kāi)始設(shè)置AndroidManiFest.xml文件
<activity android:name=".MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".Main2Activity" />
<!--這里設(shè)置了theme-->
<activity android:name=".Main3Activity"
android:theme="@android:style/Theme.Dialog">
</activity>
- 這是活動(dòng)的注冊(cè)頁(yè)面俄精,唯一不同的是在Main3Activity中設(shè)置了theme屬性,這個(gè)屬性用于指定當(dāng)前主題,這里設(shè)置的對(duì)話框的主題
- activity_mian.xml榕堰,這個(gè)主活動(dòng)的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<Button
android:id="@+id/but_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="start one"/>
<Button
android:id="@+id/but_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="start two"/>
</LinearLayout>
- 加了兩個(gè)按鈕竖慧,用于啟動(dòng)activity_mian2和activity_mian3
- 在MainActivity中添加綁定事件
public class MainActivity extends AppCompatActivity {
private static final String A = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button but_1 = (Button)findViewById(R.id.but_1);
Button but_2 = (Button)findViewById(R.id.but_2);
but_1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,Main2Activity.class);
startActivity(intent);
}
});
but_2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,Main3Activity.class);
startActivity(intent);
}
});
}
@Override
protected void onStart() {
super.onStart();
Log.d(A,"onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.d(A,"onResume");
}
@Override
protected void onPause() {
super.onPause();
Log.d(A,"onPause");
}
@Override
protected void onStop() {
super.onStop();
Log.d(A,"onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(A,"onDestroy");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(A,"onRestart");
}
}
-
注冊(cè)了兩個(gè)點(diǎn)擊事件,在Acticity的七個(gè)回調(diào)函數(shù)中打印了一句話
主頁(yè)面2018-03-13_19-51-37.png
這是看打印的信息
2018-03-13_19-52-50.png -
第一打印的onCreate(),onStart(),onResume()逆屡,圖片是應(yīng)該是這個(gè)項(xiàng)目運(yùn)行過(guò)圾旨,就沒(méi)有初始化了,然后點(diǎn)擊one Start
2018-03-13_19-56-59.png -
此時(shí)打印的信息
2018-03-13_19-57-51.png -
由于第二個(gè)頁(yè)面完全遮擋住了第一個(gè)頁(yè)面魏蔗,此時(shí)onPause()和onStop()方法都會(huì)執(zhí)行砍的,按下Back鍵返回第一個(gè)頁(yè)面
2018-03-13_20-00-26.png - 由于之前第一個(gè)頁(yè)面已經(jīng)進(jìn)入了停止的狀態(tài),所以onRestart()方法會(huì)得到執(zhí)行莺治,執(zhí)行后就是onStart()方法和onResume()方法了挨约,此時(shí)onCreate()方法不會(huì)執(zhí)行味混,因?yàn)镸ainActivity頁(yè)面滅有重新加載
- 點(diǎn)擊第二個(gè)按鈕,觀察此時(shí)的打印信息
- 這個(gè)時(shí)候只有onPause()方法得到了執(zhí)行诫惭,onStop()方法沒(méi)有得到執(zhí)行翁锡,這是因?yàn)榇藭r(shí)的頁(yè)面并沒(méi)有完全的遮蓋住MainActivity頁(yè)面,主頁(yè)面只是進(jìn)入了暫停狀態(tài)夕土,
- 按下Back鍵馆衔,只有onResume()方法會(huì)得到執(zhí)行
-
最后在MainActivity頁(yè)面,按下Back退出
2018-03-13_20-07-51.png - onPause(),onStop(),onDestroy()方法會(huì)執(zhí)行
活動(dòng)被回收了怎么辦怨绣?
- 可以想象一下角溃,在活動(dòng)A中有一個(gè)輸入框,在你輸入了一段文字后篮撑,然后啟動(dòng)了活動(dòng)B减细,那么這個(gè)時(shí)候由于系統(tǒng)的內(nèi)存不足了,這時(shí)活動(dòng)A就會(huì)被回收赢笨,這個(gè)你按Back未蝌,你會(huì)發(fā)現(xiàn)你輸入的文字不見(jiàn)了,因?yàn)榛顒?dòng)A又重新創(chuàng)建一次
- 這個(gè)時(shí)候茧妒,使用onSaveInstanceState()方法萧吠,這個(gè)方法可以保證在活動(dòng)被回收之前調(diào)用,可以通過(guò)這個(gè)方法獲取到數(shù)據(jù)得不到保存的問(wèn)題
- 這個(gè)方法可以攜帶一個(gè)布爾型的參數(shù)桐筏,可以使用putString()纸型,putInt()等保存數(shù)據(jù),一個(gè)是鍵梅忌,一個(gè)是對(duì)應(yīng)的值狰腌,在MainActivity中
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
String tempData = "Somwthing you just typed";
outState.putString("data_key",tempData);
}
- 保存的數(shù)據(jù)在哪里恢復(fù)呢,在初始化的時(shí)候牧氮,可以進(jìn)行判斷琼腔,通過(guò)savedInstanceState.getString()方法獲取到
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState != null){
String tempData = savedInstanceState.getString("data_key");
Log.d(A,tempData);
}
Button but_1 = (Button)findViewById(R.id.but_1);
Button but_2 = (Button)findViewById(R.id.but_2);
but_1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,Main2Activity.class);
startActivity(intent);
}
});
but_2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,Main3Activity.class);
startActivity(intent);
}
});
}
參考書籍:第一行代碼