轉載請註明出處:juejin.im/post/5c947a…
前言
部分內容參考Google爸爸的資料: developer.android.google.cn/guide/compo…
最近由於部門的發展需要,加上就樓主一個一線開發人員,於是乎。慘被HR當做苦力去做技術面試官。在其中樓主發現,一些一兩年經驗的開發人員對於基礎的Android知識不是很瞭解,所以打算整理一下,面試中一些技術點和麵試者對於一些問題自己新穎的看法,希望可以讓大家能夠升職加薪,走上人生巔峰。。。。 接上上一篇的文章,有喜歡的朋友可以回去檢視: 擼擼Android的羊毛(一)----Activity啟動模式 本篇將討論我們面試中經常會被問的問題,Activity的生命週期。
1.什麼是Activity
提到Activity,每個做Android開發的程式設計師都有自己的理解,“展示介面的”,“應用的前端介面”,“功能和展示的實現面”...這裡我們直接摘錄Google官網對於Activity的定義:
Activity是一個應用元件,使用者可與其提供的螢幕進行互動,以執行撥打電話、拍攝照片、傳送電子郵件或檢視地圖等操作。 每個 Activity 都會獲得一個用於繪製其使用者介面的視窗。視窗通常會充滿螢幕,但也可小於螢幕並浮動在其他視窗之上。
2.如何建立Activity
要建立Activity,就必須繼承(extends)並實現其子類,這裡我們直接使用系統原生的Activity,其他衍生類如FragmentActivity,AppCompatActivity也基本相似。
public class BActivity extends Activity {
long value; // 儲存從A傳遞過來的N值
TextView valueTextView;
TextView running;
TextView result;
long fab;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 獲取到從A傳遞過來的值
if (getIntent() != null && getIntent().hasExtra("value")) {
value = getIntent().getLongExtra("value", 0);
}
setContentView(R.layout.b_activity);
valueTextView = (TextView) findViewById(R.id.value);
running = (TextView) findViewById(R.id.running);
result = (TextView) findViewById(R.id.result);
// 將獲取到的value設定到當前的valueTextView控制元件上去
valueTextView.setText(value + "");
running.setVisibility(View.VISIBLE);
new MyThread(value).start();
}
}
複製程式碼
這需要在onCreate方法中使用setContengtView()方法定義當前Activity使用的介面。然後在AndroidManifest檔案下注冊Activity
<activity android:name=".BActivity ">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
複製程式碼
android:name 屬性是唯一必需的屬性,它指定 Activity 的類名。應用一旦釋出,即不應更改此類名,否則,可能會破壞諸如應用快捷方式等一些功能。
3. Activity 生命週期
3.1 Activity三種存在狀態
在講到Activity的生命週期之前,我們先了解一下Activity的三種存在狀態:
-
繼續 此 Activity 位於螢幕前臺並具有使用者焦點。(有時也將此狀態稱作“執行中”。)
-
暫停 另一個 Activity 位於螢幕前臺並具有使用者焦點,但此 Activity 仍可見。也就是說,另一個 Activity 顯示在此 Activity 上方,並且該 Activity 部分透明或未覆蓋整個螢幕。 暫停的 Activity 處於完全活動狀態Activity物件保留在記憶體中,它保留了所有狀態和成員資訊,並與視窗管理器保持連線),但在記憶體極度不足的情況下,可能會被系統終止。
-
停止 該 Activity 被另一個 Activity 完全遮蓋(該 Activity 目前位於“後臺”)。 已停止的 Activity 同樣仍處於活動狀態Activity 物件保留在記憶體中,它保留了所有狀態和成員資訊,但未與視窗管理器連線)。 不過,它對使用者不再可見,在他處需要記憶體時可能會被系統終止。
如果 Activity 處於暫停或停止狀態,系統可通過要求其結束(呼叫其 finish() 方法)或直接終止其程式,將其從記憶體中刪除。(將其結束或終止後)再次開啟 Activity 時,必須重建,也就是會重新呼叫onCreate方法。
3.2 Activity生命週期方法
Activity的生命週期有七個方法,這裡google的網站已經給出一張比較好的參考圖:
我們使用一個表格對Activity生命週期中的七個方法做一個總結,並且其中對每一種方法做了更詳細的描述,並說明了每一種方法在 Activity 整個生命週期內的位置,包括在方法完成後系統能否終止 Activity。
方法 | 說明 | 是否能事後終止 | 後接 |
---|---|---|---|
onCreate() | 首次建立 Activity 時呼叫。 您應該在此方法中執行所有正常的靜態設定 — 建立檢視、將資料繫結到列表等等。 系統向此方法傳遞一個 Bundle 物件,其中包含 Activity 的上一狀態,不過前提是捕獲了該狀態。始終後接 onStart()。 | 否 | onstart() |
onRestart() | 在 Activity 已停止並即將再次啟動前呼叫。始終後接 onStart() | 否 | onstart() |
onStart() | 在 Activity 即將對使用者可見之前呼叫。如果 Activity 轉入前臺,則後接 onResume(),如果 Activity 轉入隱藏狀態,則後接 onStop()。 | 否 | onResume() 或onStop() |
onResume | 在 Activity 即將開始與使用者進行互動之前呼叫。 此時,Activity 處於 Activity 堆疊的頂層,並具有使用者輸入焦點。始終後接 onPause()。 | 否 | onPause() |
onPause() | 當系統即將開始繼續另一個 Activity 時呼叫。 此方法通常用於確認對永續性資料的未儲存更改、停止動畫以及其他可能消耗 CPU 的內容,諸如此類。 它應該非常迅速地執行所需操作,因為它返回後,下一個 Activity 才能繼續執行。如果 Activity 返回前臺,則後接 onResume(),如果 Activity 轉入對使用者不可見狀態,則後接 onStop()。 | 是 | onResume() 或onStop() |
onStop() | 在 Activity 對使用者不再可見時呼叫。如果 Activity 被銷燬,或另一個 Activity(一個現有 Activity 或新 Activity)繼續執行並將其覆蓋,就可能發生這種情況。如果 Activity 恢復與使用者的互動,則後接 onRestart(),如果 Activity 被銷燬,則後接 onDestroy()。 | 是 | onRestart()或onDestroy() |
onDestory() | 在 Activity 被銷燬前呼叫。這是 Activity 將收到的最後呼叫。 當 Activity 結束(有人對 Activity 呼叫了 finish(),或系統為節省空間而暫時銷燬該 Activity 例項時,可能會呼叫它。 您可以通過 isFinishing() 方法區分這兩種情形。 | 是 | 無 |
上面的文字對於Activity的生命週期的 7個方法做了一個較為詳細的講解,但是程式設計師還是採用比較直觀的程式碼展現:
public class FirstActivity extends Activity implements OnClickListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("Activity LifeCycle","FirstActivity----->onCreate");
setContentView(R.layout.first_layout);
findViewById(R.id.pause).setOnClickListener(this);
findViewById(R.id.pause_stop).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.pause:
//跳轉到一個非全屏的activity 或者一個全透明的activity
Intent intent = new Intent(this, TransparentActivity.class);
startActivity(intent);
break;
case R.id.pause_stop:
Intent intent2 = new Intent(this, SecondActivity.class);
startActivity(intent2);
break;
}
}
@Override
protected void onStart() {
super.onStart();
Log.d("Activity LifeCycle","FirstActivity----->onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.d("Activity LifeCycle","FirstActivity----->onResume");
}
@Override
protected void onPause() {
super.onPause();
Log.d("Activity LifeCycle","FirstActivity----->onPause");
}
@Override
protected void onStop() {
super.onStop();
Log.d("Activity LifeCycle","FirstActivity----->onStop");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d("Activity LifeCycle","FirstActivity----->onRestart");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d("Activity LifeCycle","FirstActivity----->onDestroy");
}
}
複製程式碼
之後我們會使用該類來實現相應的操作,驗證流程。 首先,我們進入該activity,
然後我們檢視logcat下的日誌 此時activity經過onCreate--->onStart--->onResume,Activity獲取到焦點,並展示在介面上。 然後我們點選home鍵,這時logcat日誌如下: 過程中activity經過onPause---->onStop最終是去焦點,並退到後臺棧中。 再次啟動該介面,logcat展示: 在這過程中activity經過onStart---->onResume 最終獲取焦點,展示在介面上。 我們退出該介面,logcat展示如下: 在這過程中activity經過onPause-->onStop--->onDestroy.結合之前的google官方圖,能夠很好的瞭解Activity的生命週期學習的參考專案在我的github下,該專案是我從學習到現在整理的一些常用資料,歡迎大家star github.com/jixiang5200…