編輯:關於Android編程
我們都知道android中有四大組件(Activity 活動,Service 服務,Content Provider 內容提供者,BroadcastReceiver 廣播接收器),Activity是我們用的最多也是最基本的組件,因為應用的所有操作都與用戶相關,Activity 提供窗口來和用戶進行交互。
官方文檔這麼說:
An activity is a single, focused thing that the user can do. Almost all activities interact with the user, so the Activity class takes care of creating a window for you in which you can place your UI with setContentView(View).
大概的意思(原諒我):
activity是獨立平等的,用來處理用戶操作。幾乎所有的activity都是用來和用戶交互的,所以activity類會創建了一個窗口,開發者可以通過setContentView(View)的接口把UI放到給窗口上。
Android中的activity全都歸屬於task管理 。task 是多個 activity 的集合,這些 activity 按照啟動順序排隊存入一個棧(即“back stack”)。android默認會為每個App維持一個task來存放該app的所有activity,task的默認name為該app的packagename。
當然我們也可以在AndroidMainfest.xml中申明activity的taskAffinity屬性來自定義task,但不建議使用,如果其他app也申明相同的task,它就有可能啟動到你的activity,帶來各種安全問題(比如拿到你的Intent)。
上面已經說了,系統通過堆棧來管理activity,當一個新的activity開始時,它被放置在堆棧的頂部和成為運行活動,以前的activity始終保持低於它在堆棧,而不會再次到達前台,直到新的活動退出。
還是上這張官網的activity_lifecycle圖:
首先打開一個新的activity實例的時候,系統會依次調用
onCreate() -> onStart() -> onResume() 然後開始running
running的時候被覆蓋了(從它打開了新的activity或是被鎖屏,但是它依然在前台運行, lost focus but is still visible),系統調用onPause();
該方法執行activity暫停,通常用於提交未保存的更改到持久化數據,停止動畫和其他的東西。但這個activity還是完全活著(它保持所有的狀態和成員信息,並保持連接到窗口管理器)
接下來它有三條出路
①用戶返回到該activity就調用onResume()方法重新running
②用戶回到桌面或是打開其他activity,就會調用onStop()進入停止狀態(保留所有的狀態和成員信息,對用戶不可見)
③系統內存不足,擁有更高限權的應用需要內存,那麼該activity的進程就可能會被系統回收。(回收onRause()和onStop()狀態的activity進程)要想重新打開就必須重新創建一遍。
如果用戶返回到onStop()狀態的activity(又顯示在前台了),系統會調用
onRestart() -> onStart() -> onResume() 然後重新running
在activity結束(調用finish ())或是被系統殺死之前會調用onDestroy()方法釋放所有占用的資源。
activity生命周期中三個嵌套的循環
activity的完整生存期會在 onCreate() 調用和 onDestroy() 調用之間發生。
activity的可見生存期會在 onStart() 調用和 onStop() 調用之間發生。系統會在activity的整個生存期內多次調用 onStart() 和onStop(), 因為activity可能會在顯示和隱藏之間不斷地來回切換。
activity的前後台切換會在 onResume() 調用和 onPause() 之間發生。
因為這個狀態可能會經常發生轉換,為了避免切換遲緩引起的用戶等待,這兩個方法中的代碼應該相當地輕量化。
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
if(savedInstanceState!=null){ //判斷是否有以前的保存狀態信息
savedInstanceState.get("Key");
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
//可能被回收內存前保存狀態和信息,
Bundle data = new Bundle();
data.putString("key", "last words before be kill");
outState.putAll(data);
super.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
// TODO Auto-generated method stub
if(savedInstanceState!=null){ //判斷是否有以前的保存狀態信息
savedInstanceState.get("Key");
}
super.onRestoreInstanceState(savedInstanceState);
}
}
onSaveInstanceState方法
在activity 可能被回收之前 調用,用來保存自己的狀態和信息,以便回收後重建時恢復數據(在onCreate()或onRestoreInstanceState()中恢復)。旋轉屏幕重建activity會調用該方法,但其他情況在onRause()和onStop()狀態的activity不一定會調用 ,下面是該方法的文檔說明。
One example of when onPause and onStop is called and not this method is when a user navigates back from activity B to activity A: there is no need to call onSaveInstanceState on B because that particular instance will never be restored, so the system avoids calling it. An example when onPause is called and not onSaveInstanceState is when activity B is launched in front of activity A: the system may avoid calling onSaveInstanceState on activity A if it isn't killed during the lifetime of B since the state of the user interface of A will stay intact.
也就是說,系統靈活的來決定調不調用該方法,但是如果要調用就一定發生在onStop方法之前,但並不保證發生在onPause的前面還是後面。
onRestoreInstanceState方法
這個方法在onStart 和 onPostCreate之間調用,在onCreate中也可以狀態恢復,但有時候需要所有布局初始化完成後再恢復狀態。
onPostCreate:一般不實現這個方法,當程序的代碼開始運行時,它調用系統做最後的初始化工作。
簡單的說就是定義activity 實例與task 的關聯方式。
為了實現一些默認啟動(standard)模式之外的需求:
讓某個 activity 啟動一個新的 task (而不是被放入當前 task )
讓 activity 啟動時只是調出已有的某個實例(而不是在 back stack 頂創建一個新的實例)
或者,你想在用戶離開 task 時只保留根 activity,而 back stack 中的其它 activity 都要清空
定義啟動模式的方法有兩種:
在 manifest 文件中activity聲明時,利用 activity 元素的 launchMode 屬性來設定 activity 與 task 的關系。
.......
注意: 你用 launchMode 屬性為 activity 設置的模式可以被啟動 activity 的 intent 標志所覆蓋。
“standard” (默認模式)
當通過這種模式來啟動Activity時, Android總會為目標 Activity創建一個新的實例,並將該Activity添加到當前Task棧中。這種方式不會啟動新的Task,只是將新的 Activity添加到原有的Task中。
“singleTop”
該模式和standard模式基本一致,但有一點不同:當將要被啟動的Activity已經位於Task棧頂時,系統不會重新創建目標Activity實例,而是直接復用Task棧頂的Activity。
“singleTask”
Activity在同一個Task內只有一個實例。
如果將要啟動的Activity不存在,那麼系統將會創建該實例,並將其加入Task棧頂;
如果將要啟動的Activity已存在,且存在棧頂,直接復用Task棧頂的Activity。
如果Activity存在但是沒有位於棧頂,那麼此時系統會把位於該Activity上面的所有其他Activity全部移出Task,從而使得該目標Activity位於棧頂。
“singleInstance”
無論從哪個Task中啟動目標Activity,只會創建一個目標Activity實例且會用一個全新的Task棧來裝載該Activity實例(全局單例).
如果將要啟動的Activity不存在,那麼系統將會先創建一個全新的Task,再創建目標Activity實例並將該Activity實例放入此全新的Task中。
如果將要啟動的Activity已存在,那麼無論它位於哪個應用程序,哪個Task中;系統都會把該Activity所在的Task轉到前台,從而使該Activity顯示出來。
在要啟動 activity 時,你可以在傳給 startActivity() 的 intent 中包含相應標志,以修改 activity 與 task 的默認關系。
Intent i = new Intent(this,NewActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
FLAG_ACTIVITY_NEW_TASK
與”singleTask”模式相同,在新的 task 中啟動 activity。如果要啟動的 activity 已經運行於某 task 中,則那個 task 將調入前台。
FLAG_ACTIVITY_SINGLE_TOP
與 “singleTop”模式相同,如果要啟動的 activity位於back stack 頂,系統不會重新創建目標Activity實例,而是直接復用Task棧頂的Activity。
FLAG_ACTIVITY_CLEAR_TOP
此種模式在launchMode中沒有對應的屬性值。如果要啟動的 activity 已經在當前 task 中運行,則不再啟動一個新的實例,且所有在其上面的 activity 將被銷毀。
一般不要改變 activity 和 task 默認的工作方式。 如果你確定有必要修改默認方式,請保持謹慎,並確保 activity 在啟動和從其它 activity 返回時的可用性,多做測試和安全方面的工作。
android的3個核心組件——Activity、services、廣播接收器——是通過intent傳遞消息的。intent消息用於在運行時綁定不同的組件。
在 Android 的 AndroidManifest.xml 配置文件中可以通過 intent-filter 節點為一個 Activity 指定其 Intent Filter,以便告訴系統該 Activity 可以響應什麼類型的 Intent。
一個 Intent Filter 可以包含多個 Action,Action 列表用於標示 Activity 所能接受的“動作”,它是一個用戶自定義的字符串。
……
在代碼中使用以下語句便可以啟動該Intent 對象:
Intent i=new Intent();
i.setAction("com.scu.amazing7Action");
Action 列表中包含了“com.scu.amazing7Action”的 Activity 都將會匹配成功
在 intent-filter 節點中,通過 data節點匹配外部數據,也就是通過 URI 攜帶外部數據給目標組件。
注意:只有data的所有的屬性都匹配成功時 URI 數據匹配才會成功
為組件定義一個 類別列表,當 Intent 中包含這個類別列表的所有項目時才會匹配成功。
①加載所有的Intent Filter列表
②去掉action匹配失敗的Intent Filter
③去掉url匹配失敗的Intent Filter
④去掉Category匹配失敗的Intent Filter
⑤判斷剩下的Intent Filter數目是否為0。如果為0查找失敗返回異常;如果大於0,就按優先級排序,返回最高優先級的Intent Filter
一般設置Activity為非公開的
注意:非公開的Activity不能設置intent-filter,以免被其他activity喚醒(如果擁有相同的intent-filter)。
不要指定activity的taskAffinity屬性
不要設置activity的LaunchMode(保持默認)
注意Activity的intent最好也不要設定為FLAG_ACTIVITY_NEW_TASK
在匿名內部類中使用this時加上activity類名(類名.this,不一定是當前activity)
設置activity全屏
在其 onCreate()方法中加入:
// 設置全屏模式
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
// 去除標題欄
requestWindowFeature(Window.FEATURE_NO_TITLE);
覺得有幫助的,頂一下,謝謝!
status_t Camera::connectLegacy(int cameraId, int halVersion, const String16&
IntentService(Service)的使用場景 IntentService與Service的區別 IntentService使用 IntentService原理源
背景最近需要實現一個自定義Notification的功能。網上找了找代碼,解決方案就是通過RemoteViews來實現。但是在實現過程中遇到不少問題,網上也沒有很好的文章
要說攔截Android系統來電,就不得不說起在低版本的時候Android提供給開發者使用的一個方法:endCall(),但由於谷歌後來考慮到對於一部手機來說,最重要的功能