擼擼Android的羊毛(二)----Activity生命週期

吉祥發表於2019-03-22

轉載請註明出處: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的網站已經給出一張比較好的參考圖:

acivity的生命週期

我們使用一個表格對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,

image.png
然後我們檢視logcat下的日誌
image.png
此時activity經過onCreate--->onStart--->onResume,Activity獲取到焦點,並展示在介面上。 然後我們點選home鍵,這時logcat日誌如下:
image.png
過程中activity經過onPause---->onStop最終是去焦點,並退到後臺棧中。 再次啟動該介面,logcat展示:
image.png
在這過程中activity經過onStart---->onResume 最終獲取焦點,展示在介面上。 我們退出該介面,logcat展示如下:
image.png
在這過程中activity經過onPause-->onStop--->onDestroy.結合之前的google官方圖,能夠很好的瞭解Activity的生命週期

學習的參考專案在我的github下,該專案是我從學習到現在整理的一些常用資料,歡迎大家star github.com/jixiang5200…

相關文章