.Activity的本質html
Activity是Android提供的四大組件之一,是進行Android開發必不可少的組件.Activity是一個界面的載體,能夠把它與html頁面進行類比,html頁面由各類各樣的標籤組成,而Activity則能夠由各類控件組成.然而Activity也並非那麼簡單.查看Activity類的源碼咱們就能夠看到,這個類大概有六千多行代碼,說明Android對Activity的處理是至關複雜的.不過咱們平時進行開發的時候不須要了解到那麼深刻的地步,由於咱們能夠根據Activity中提供的方法快速的開發,Activity生命週期中涉及到七個回調方法.java
.Activity的生命週期android
Android官方文檔給出的Activity生命週期圖web
當打開一個Activity的時候,會調用這個Activity的onCreate()方法,接着調用onStart()方法,而後調用onResume()方法.當onStart()方法執行以後,咱們就能夠看到這個Activity界面了.下面經過代碼對單個Activity生命週期作進一步的解釋.數組
MainActivity.java瀏覽器
package com.example.caobotao.activitylifecircle; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.i("info","MainActivity onCreate()"); } @Override protected void onStart() { super.onStart(); Log.i("info","MainActivity onStart()"); } @Override protected void onResume() { super.onResume(); Log.i("info","MainActivity onResume()"); } @Override protected void onPause() { super.onPause(); Log.i("info", "MainActivity onPause()"); } @Override protected void onStop() { super.onStop(); Log.i("info", "MainActivity onStop()"); } @Override protected void onDestroy() { super.onDestroy(); Log.i("info","MainActivity onDestroy()"); } @Override protected void onRestart() { super.onRestart(); Log.i("info","MainActivity onRestart()"); } }
運行項目後,Logcat輸出:安全
11-24 20:00:49.160 20104-20104/com.example.caobotao.activitylifecircle I/info: MainActivity onCreate() 11-24 20:00:49.170 20104-20104/com.example.caobotao.activitylifecircle I/info: MainActivity onStart() 11-24 20:00:49.170 20104-20104/com.example.caobotao.activitylifecircle I/info: MainActivity onResume()
點擊返回鍵,Logcat輸出:數據結構
11-24 20:05:15.370 20104-20104/com.example.caobotao.activitylifecircle I/info: MainActivity onStop() 11-24 20:05:15.370 20104-20104/com.example.caobotao.activitylifecircle I/info: MainActivity onDestroy()
下面簡單講一下Activity生命週期中每一個函數的做用:app
onCreate() : ide
當Activity第一次被建立的時候調用此方法.通常在此方法中進行控件的聲明,添加事件等初始化工做.
onStart():
當Activity被顯示到屏幕上的時候調用此方法.
onResume():
當此Activity可以被操做以前,也就是可以得到用戶的焦點以前調用此方法.
onRestart():
當Activity被中止後又被再次啓動以前調用此方法.接着將調用onStart()方法.
onPause():
當第一個Activity經過Intent啓動第二個Activity的時候,將調用第一個Activity的onPause()方法.而後調用第二個Activity的onCreate(),onStart(),onResume()方法,接着調用第一個Activity的onStop()方法.若是Activity從新得到焦點,則將調用onResume()方法;若是此Activity進入用戶不可見狀態,那麼將調用onStop()方法.
onStop():
當第一個Activity被第二個Activity徹底覆蓋,或者被銷燬的時候回調用此方法.若是此Activity還會與用戶進行交互,將調用onRestart方法();若是此Activity將被銷燬,那麼將調用onDestroy()方法.
onDestroy():
Activity被銷燬以前調用此方法.或者是調用finish()方法結束Activity的時候調用此方法.能夠在此方法中進行收尾工做,好比釋放資源等.
(注意:重寫某個Activity的這些回調方法的時候須要首先在第一行調用基類Activity的相應的回調方法.好比super.onCreate(),super.onStart()等等.)
接下來了解一下多個Activity交互中的生命週期.在第一個Activity中添加一個按鈕,用於啓動第二個Activity.
AActivity.java
package com.example.caobotao.activitylifecircle; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; public class AActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.i("info","AActivity onCreate()"); findViewById(R.id.btnStartBAty).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(AActivity.this,BActivity.class)); } }); } @Override protected void onStart() { super.onStart(); Log.i("info","AActivity onStart()"); } @Override protected void onResume() { super.onResume(); Log.i("info","AActivity onResume()"); } @Override protected void onPause() { super.onPause(); Log.i("info", "AActivity onPause()"); } @Override protected void onStop() { super.onStop(); Log.i("info", "AActivity onStop()"); } @Override protected void onDestroy() { super.onDestroy(); Log.i("info","AActivity onDestroy()"); } @Override protected void onRestart() { super.onRestart(); Log.i("info","AActivity onRestart()"); } }
BActivity.java
package com.example.caobotao.activitylifecircle; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; public class BActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_baty); Log.i("info","BActivity oncreate()"); } @Override protected void onStart() { super.onStart(); Log.i("info","BActivity onStart()"); } @Override protected void onResume() { super.onResume(); Log.i("info","BActivity onResume()"); } @Override protected void onStop() { super.onStop(); Log.i("info","BActivity onStop()"); } @Override protected void onDestroy() { super.onDestroy(); Log.i("info", "BActivity onDestroy()"); } @Override protected void onRestart() { super.onRestart(); Log.i("info","BActivity onRestart()"); } }
運行項目後,Logcat輸出:
11-26 21:14:38.960 6208-6208/com.example.caobotao.activitylifecircle I/info: AActivity onCreate() 11-26 21:14:38.970 6208-6208/com.example.caobotao.activitylifecircle I/info: AActivity onStart() 11-26 21:14:38.970 6208-6208/com.example.caobotao.activitylifecircle I/info: AActivity onResume()
點擊按鈕打開BActivity後,Logcat輸出:
11-26 21:14:42.050 6208-6208/com.example.caobotao.activitylifecircle I/info: AActivity onPause() 11-26 21:14:42.080 6208-6208/com.example.caobotao.activitylifecircle I/info: BActivity oncreate() 11-26 21:14:42.090 6208-6208/com.example.caobotao.activitylifecircle I/info: BActivity onstart() 11-26 21:14:42.090 6208-6208/com.example.caobotao.activitylifecircle I/info: BActivity onresume() 11-26 21:14:45.750 6208-6208/com.example.caobotao.activitylifecircle I/info: AActivity onstop()
而後點擊BACK鍵,Logcat輸出:
11-26 21:20:38.650 6208-6208/com.example.caobotao.activitylifecircle I/info: BActivity onPause() 11-26 21:20:38.970 6208-6208/com.example.caobotao.activitylifecircle I/info: AActivity onRestart() 11-26 21:20:38.970 6208-6208/com.example.caobotao.activitylifecircle I/info: AActivity onStart() 11-26 21:20:38.970 6208-6208/com.example.caobotao.activitylifecircle I/info: AActivity onResume() 11-26 21:20:41.710 6208-6208/com.example.caobotao.activitylifecircle I/info: BActivity onStop() 11-26 21:20:41.710 6208-6208/com.example.caobotao.activitylifecircle I/info: BActivity onDestroy()
能夠看出,當啓動第二個Activity時,老是先調用第一個Activity的onPause()方法,而後若是第二個Activity是第一次建立的話,則再調用第二個Activity的onCreate()方法,不然調用第二個Activity的onRestart()方法,接着調用onStart(),onResume()方法.
.Activity生命週期交互設計思想
到這裏,你們可能會有些疑問,谷歌爲何要這樣設計呢?如:
1.當從第一個Activity啓動第二個Activity的時候,爲何先調用第一個Activity的onPause()方法,而後再調用第二個Activity的onCreate()等方法呢?
解釋:假若有這樣一個狀況,你正在使用APP聽音樂,忽然來了一個電話,那麼固然須要先暫停音樂,而後進行電話的處理。因此這就是onPause()方法的做用:能夠用來保存當前的各類信息.能夠在這個APP的onPause()方法中實現暫停音樂的邏輯,而後再處理電話的業務處理.
2.當從第一個Activity啓動第二個Activity的時候,爲何第一個Activity的onStop()方法是調用完第二個Activity的系列方法後才調用呢,爲何不在第一個Activity的onPause()方法以後就調用呢?
解釋:這是谷歌對安全方面的一個考慮.假如先調用第一個Activity的onStop()方法,那麼此時第一個Activity將不可見,若是接下來調用第二個Activity的一系列建立方法失敗了,那麼就會致使這兩個Activity都沒顯示在屏幕上,就會出現黑屏等不友好界面.若是是調用完第二個Activity一系列建立方法後,再調用第一個Activity的onStop()方法,就會避免這種狀況的發生.
.Activity生命週期的應用場景
講了這麼多,你們可能會問,Activity生命週期到底實際中怎麼使用.下面經過實例來作簡單的運用.在AActivity中進行音樂的播放,當點擊按鈕打開BActivity後,音樂須要暫停,而後點擊BACK鍵返回到AActivity後音樂繼續播放.這就須要在AActivity中的onPause()方法中進行音樂的暫停操做,以及暫停時音樂播放位置的記錄.在AActivity中的onResume()方法中實現從新返回前臺時繼續音樂的播放.
AActivity.java
package com.example.caobotao.activitylifecircle; import android.app.Activity; import android.content.Intent; import android.media.MediaPlayer; import android.os.Bundle; import android.util.Log; import android.view.View; public class AActivity extends Activity { private MediaPlayer mediaPlayer; private int position; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mediaPlayer = MediaPlayer.create(this,R.raw.song); mediaPlayer.start(); Log.i("info","AActivity onCreate()"); findViewById(R.id.btnStartBAty).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(AActivity.this,BActivity.class)); } }); } @Override protected void onStart() { super.onStart(); Log.i("info","AActivity onStart()"); } @Override protected void onResume() { super.onResume(); //若是播放的位置不是0 if (position != 0){ mediaPlayer.seekTo(position);//獲取播放的位置 mediaPlayer.start();//開始播放 } Log.i("info","AActivity onResume()"); } @Override protected void onPause() { super.onPause(); //若是播放器正在播放 if (mediaPlayer.isPlaying()){ mediaPlayer.pause();//暫停播放 position = mediaPlayer.getCurrentPosition();//得到暫停時播放的位置 } Log.i("info", "AActivity onPause()"); } @Override protected void onStop() { super.onStop(); Log.i("info", "AActivity onStop()"); } @Override protected void onDestroy() { super.onDestroy(); Log.i("info","AActivity onDestroy()"); } @Override protected void onRestart() { super.onRestart(); Log.i("info","AActivity onRestart()"); } }
BActivity.java
package com.example.caobotao.activitylifecircle; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; public class BActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_baty); Log.i("info","BActivity onCreate()"); } @Override protected void onStart() { super.onStart(); Log.i("info","BActivity onStart()"); } @Override protected void onResume() { super.onResume(); Log.i("info","BActivity onResume()"); } @Override protected void onPause() { super.onPause(); Log.i("info","BActivity onPause()"); } @Override protected void onStop() { super.onStop(); Log.i("info","BActivity onStop()"); } @Override protected void onDestroy() { super.onDestroy(); Log.i("info", "BActivity onDestroy()"); } @Override protected void onRestart() { super.onRestart(); Log.i("info","BActivity onRestart()"); } }
.其餘應用程序中的Activity
咱們能夠經過ComponentName啓動其餘應用程序中的Activity,好比啓動相機等.
用法:
Intent intent=new Intent(); intent.setComponent(new ComponentName(String packageName,String activityName )); startActivity(intent);
.啓動系統中常見的Activity
系統給咱們提供了不少經常使用的Activity,能夠用來打開瀏覽器,打開發短信界面,打開相冊界面,打開撥號界面等等.
打開瀏覽器網頁:
Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
打開相冊:
Intent intent = new Intent(); intent.setAction(Intent.ACTION_GET_CONTENT); intent.setType("image/*"); startActivity(intent);
打開發送短信界面:
Intent intent = new Intent(); intent.setAction(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_TEXT,"Hello World !"); startActivity(intent);
打開撥號界面:
Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); intent.setData(Uri.parse("tel:110")); startActivity(intent);
.Activity之間的數據交互
咱們可使用Intent對象進行數據的傳遞.Intent重載了不少putExtra()方法,囊括了JAVA八大基本類型及其數組類型等.
Activity1.java
package com.example.caobotao.activitylifecircle; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; /** * Created by caobotao on 15/11/29. */ public class Activity1 extends Activity { private Button button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity1); button = (Button) findViewById(R.id.startAnotherActivity); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(Activity1.this,Activity2.class); intent.putExtra("name","zhangsan"); intent.putExtra("age",23); startActivity(intent); } }); } }
Activity2.java
package com.example.caobotao.activitylifecircle; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.widget.TextView; /** * Created by caobotao on 15/11/29. */ public class Activity2 extends Activity { private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity2); textView = (TextView) findViewById(R.id.textView); Intent intent = getIntent(); if (intent != null){ String name = intent.getStringExtra("name"); int age = intent.getIntExtra("age",0);//設0爲默認值 textView.setText("姓名: " + name + "\n年齡: " + age); } } }
Intent對象還有一個putExtras(Bundle bundle)方法,bundle的意思爲一捆,就是把須要傳遞的數據打成一捆進行傳遞.下面利用Bundle實現上面的示例,效果同樣.
Activity1.java
package com.example.caobotao.activitylifecircle; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; /** * Created by caobotao on 15/11/29. */ public class Activity1 extends Activity { private Button button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity1); button = (Button) findViewById(R.id.startAnotherActivity); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(Activity1.this,Activity2.class); Bundle bundle = new Bundle(); bundle.putString("name","zhangsan"); bundle.putInt("age",23); intent.putExtras(bundle); startActivity(intent); } }); } }
Activity2.java
package com.example.caobotao.activitylifecircle; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.widget.TextView; /** * Created by caobotao on 15/11/29. */ public class Activity2 extends Activity { private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity2); textView = (TextView) findViewById(R.id.textView); Intent intent = getIntent(); if (intent != null){ String name = intent.getStringExtra("name"); int age = intent.getIntExtra("age",0);//設0爲默認值 textView.setText("姓名: " + name + "\n年齡: " + age); } } }
在實際開發中,可能須要傳遞的數據比較多,不只有姓名,年齡,可能還有性別,學校,愛好等等.根據面向對象的思想,咱們應該想到把這些信息封裝成一個java實體類,以達到更好的複用性,耦合性等目的,而後使用Bundle對象的putSerializable()方法將此須要傳遞的對象傳遞出去,在另外一個Activity中用Intent對象的getSerializableExtra()方法進行接收.
Person.java
package com.example.caobotao.activitylifecircle; import java.io.Serializable; /** * Created by caobotao on 15/11/29. */ public class Person implements Serializable { private String name; private int age; private String school; private String address; public Person(){} public Person(String name,int age,String school,String address){ this.name = name; this.age = age; this.school = school; this.address = address; } @Override public String toString() { return "姓名: " + name + "\n年齡: " + age + "\n學校: " + school + "\n地址: " + address; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSchool() { return school; } public void setSchool(String school) { this.school = school; } }
Activity1.java
package com.example.caobotao.activitylifecircle; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; /** * Created by caobotao on 15/11/29. */ public class Activity1 extends Activity { private Button button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity1); button = (Button) findViewById(R.id.startAnotherActivity); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(Activity1.this,Activity2.class); Person person = new Person("zhangsan",23,"USST","ShangHai"); Bundle bundle = new Bundle(); bundle.putSerializable("person",person); intent.putExtras(bundle); startActivity(intent); } }); } }
Activity2.java
package com.example.caobotao.activitylifecircle; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.widget.TextView; /** * Created by caobotao on 15/11/29. */ public class Activity2 extends Activity { private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity2); textView = (TextView) findViewById(R.id.textView); Intent intent = getIntent(); if (intent != null) { Person person = (Person) intent.getSerializableExtra("person"); textView.setText(person.toString()); } } }
.Task與Back Stack(引自官方文檔)
task 是一系列被操做的 activity 的集合,用戶進行操做時將與這些 activity 進行交互。 這些 activity 按照啓動順序排隊存入一個棧(即「back stack」)。咱們知道棧是一個後進先出的數據結構,在一個task中,每打開一個新的activity,就會將其壓入棧頂的位置;每次點擊Back鍵,棧頂的activity就會被移除.
大部分 task 都啓動自 Home 屏幕。當用戶觸摸 application launcher 中的圖標(或 Home 屏幕上的快捷圖標)時,應用程序的 task 就進入前臺。 若是該應用不存在 task(最近沒有使用過此應用),則會新建一個 task,該應用的「main」activity 做爲棧的根 activity 被打開。
當用戶返回到 home屏幕執行另外一個 task 時,一個 task 被移動到後臺執行,此時它的返回棧(back stack)也被保存在後臺, 同時 android 爲新 task 建立一個新的返回棧(back stack),當它被再次運行從而返回前臺時,它的返回棧(back stack)被移到前臺,並恢復其以前執行的activity,以下圖所示。 若是後臺有太多運行 task ,系統將會殺死一些 task 釋放內存。
若是當前 activity 啓動了另外一個 activity,則新的 activity 被壓入棧頂並得到焦點。 前一個 activity 仍保存在棧中,可是被中止。activity 中止時,系統會保存用戶界面的當前狀態。 當用戶按下返回鍵,則當前 activity 將從棧頂彈出(被銷燬),前一個 activity 將被恢復(以前的用戶界面狀態被恢復)。 activity 在棧中的順序永遠不會改變,只會壓入和彈出——被當前 activity 啓動時壓入棧頂,用戶用返回鍵離開時彈出。 這樣,back stack 以「後進先出」的方式運行。下圖以時間線的方式展現了多個 activity 切換時對應當前時間點的 back stack 狀態。
圖: task 中的每一個新 activity 都會相應在 back stack 中增長一項。當用戶按下返回鍵時,
當前 activity 被銷燬,前一個 activity 被恢復。
若是用戶不停地按下返回鍵,則棧中每一個 activity 都會依次彈出,並顯示前一個 activity,直至用戶回到 Home 屏幕(或者任一啓動該 task 的 activity)。 當全部 activity 都從棧中彈出後, task 就此消失。
.Activity啓動模式(引自官方文檔)
在 manifest 文件中聲明 activity 時,你能夠利用activity元素的launchMode屬性來設定 activity 與 task 的關係。
launchMode 屬性指明瞭 activity 啓動 task 的方式。 launchMode 屬性可設爲四種啓動模式:
singleTop:
注意: 一個 activity 的新實例建立完畢後,用戶能夠按回退鍵返回前一個 activity。 可是當 activity 已有實例正在處理剛到達的 intent 時,用戶沒法用回退鍵回到 onNewIntent() 中 intent 到來以前的 activity 狀態。
注意: 雖然 activity 啓動了一個新的 task,但用戶仍然能夠用回退鍵返回前一個 activity。
singleInstance:
舉個例子,Android 的瀏覽器應用就把 web 瀏覽器 activity 聲明爲老是在它本身獨立的 task 中打開——把 activity設爲singleTask模式。 這意味着,若是你的應用提交 intent 來打開 Android 的瀏覽器,則其 activity 不會被放入你的應用所在的 task 中。 取而代之的是,或是爲瀏覽器啓動一個新的 task;或是瀏覽器已經在後臺運行,只要把 task 調入前臺來處理新 intent 便可。
不管 activity 是在一個新的 task 中啓動,仍是位於其它已有的 task 中,用戶老是能夠用回退鍵返回到前一個 activity 中。 可是,若是你啓動了一個啓動模式設爲singleTask的 activity,且有一個後臺 task 中已存在實例的話,則這個後臺 task 就會整個轉到前臺。 這時,當前的 back stack 就包含了這個轉入前臺的 task 中全部的 activity,位置是在棧頂。下圖就展現了這種場景。
圖 . 啓動模式爲「singleTask」的 activity 如何加入 back stack 的示意圖。 若是 activity 已是在後臺 task 中並帶有
本身的 back stack,則整個後臺 back stack 都會轉入前臺,並放入當前 task 的棧頂。