Activity之Intent、生命週期、啓動模式

1.Activity的理解

  • Activity 直譯爲活動,它是Android定義的四大應用組件之一,也是最重要用的最多的
  • Activity用來提供一個能讓用戶操作並與之交互的界面
  • 一個應用有多個界面,也就是包含多個Activity(還存在單Activity+多Fragment 的)
  • 打電話、發短信、拍照、發郵件等功能都是通過Activity來做的

2.Intent的理解

  • Intent 直譯爲意圖,也就是你想要做什麼或想去哪
  • Intent是ActivityServiceBroadcastRecevier這個三個應用組件之間通信的信使
  • 例如: 我要在Activity中啓動另一個Actvity, 就必須使用Intent對象

  • 意圖對象還可以攜帶數據
  • 注意: Intent不是Android中的四大應用組件之一
  • Intent的分類:顯式意圖 : 明確指定的目標組件的意圖 創建對象 : Intent(Context context, Class clazz) 何時使用 : 當操作當前自己應用的組件時使用。
                          隱式意圖 : 沒有明確指定目標組件的意圖 創建對象 : Intent(String action) 何時使用 : 當操作其它應用的組件時。使用

        注:在Intent內部維護了一個HashMap<String,Objec>

2.1 IntentFilter的理解

  • 在配置Activity時, 可以爲Activity指定一個IntentFilter的配置
  • 如果你的Activity希望其它應用能訪問到, 需要配置<intent-filter>
  • 如果你想啓動其它應用的界面你必須用隱式intent, 且目標界面Activty配置了<intent-filter>
  • 它的作用類似於web中的爲Servlet配置的<url-pattern>

2.2 Intent的七大屬性(ComponentName、Action、Category、Data、Type、Extra、Flag

Intent七大屬性是指Intent的ComponentName、Action、Category、Data、Type、Extra、Flag,七個屬性,總體上可以分爲3類:

第一類:啓動,有ComponentName(顯式),Action(隱式),Category(隱式)。

第二類:傳值,有Data(隱式),Type(隱式),Extra(隱式、顯式)。

第三類:啓動模式,有Flag。

  • ComponentName: 用於指出啓動的組件(實現頁面的跳轉)
intent = new Intent();
intent.setComponent(new ComponentName(this, SecondActivity.class));
startActivity(intent);
  • Action:Action屬性的值爲一個字符串,它代表了系統中已經定義了一系列常用的動作。通過setAction()方法或在清單文件AndroidManifest.xml中設置。默認爲:DEFAULT。
          Action、Category屬性與intent-filter配置:通常,Action、Category屬性結合使用,定義這兩個屬性都是在配置文件的<intent-filter>節點中。Intent通過定義Action屬性(其實就是一段自定義的字符串),這樣就可以把Intent與具體的某個Activity分離,實現瞭解耦。否則,每次跳轉,都要寫成類似new Intent(MainActivity.this,NextActivity.class)這樣的形式,也就是說必須將要跳轉的目標Activity的名字寫出來,這樣的編碼其實是“硬編碼”,並沒有實現松耦合。調用Intent對象的setAction()方法實現頁面跳轉雖然略微複雜(需要在AndroidManifest.xml文件中配置)
    1、示例代碼:
    Intent intent = new Intent(); 
    intent.setAction("com.train.task01.editactivity"); 
    startActivity(intent);
    //在配置文件中註冊Activity的時候需要聲明:
    <activity android:name="com.train.taskstack01.EditActivity">
      <intent-filter>
          <action android:name="com.train.task01.editactivity" />
          <category android:name="android.intent.category.DEFAULT" />   
      </intent-filter>
    </activity>
    //當某個頁面是默認啓動頁面時,需要定義Action、Category的屬性必須爲以下字符串:【設置任務入口】
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
    
    
    常用的屬性
    ACTION_MAIN:(android.intent.action.MAIN)Android程序入口,每個Android應用必須且只能包含一個此類型的Action聲明。 
    ACTION_VIEW: (android.intent.action.VIEW) 顯示指定數據。
    ACTION_EDIT: (android.intent.action.EDIT) 編輯指定數據。 
    ACTION_DIAL: (android.intent.action.DIAL) 顯示撥號面板。
    ACTION_CALL: (android.intent.action.CALL) 直接呼叫Data中所帶的號碼。  
    ACTION_ANSWER: (android.intent.action.ANSWER) 接聽來電。  
    ACTION_SEND: (android.intent.action.SEND) 向其他人發送數據(例如:彩信/email)。  
    ACTION_SENDTO:  (android.intent.action.SENDTO) 向其他人發送短信。
    ACTION_SEARCH: (android.intent.action.SEARCH) 執行搜索。  
    ACTION_GET_CONTENT: (android.intent.action.GET_CONTENT) 讓用戶選擇數據,並返回所選數據
    ACTION_BOOT_COMPLETED:Android系統在啓動完畢後發出帶有此Action的廣播(Broadcast)。 
    ACTION_TIME_CHANGED:Android系統的時間發生改變後發出帶有此Action的廣播(Broadcast)。 
    ACTION_PACKAGE_ADDED:Android系統安裝了新的Application之後發出帶有此Action的廣播(Broadcast)。 
    ACTION_PACKAGE_CHANGED:Android系統中已存在的Application發生改變之後(如應用更新操作)發出帶有此Action的廣播(Broadcast)。 
    ACTION_PACKAGE_REMOVED:卸載了Android系統已存在的Application之後發出帶有此Action的廣播(Broadcast)。  

    Category:Category屬性用於指定當前動作(Action)被執行的環境。通過addCategory()方法或在清單文件AndroidManifest.xml中設置。默認爲:CATEGORY_DEFAULT。
    Intent intent = new Intent(); 
    intent.setAction(Intent.ACTION_MAIN); 
    intent.addCategory(Intent.CATEGORY_HOME); 
    startActivity(intent); 
    
    常用屬性
    CATEGORY_DEFAULT: (android.intent.category.DEFAULT) Android系統中默認的執行方式,按照普通Activity的執行方式執行。 
    CATEGORY_HOME: (android.intent.category.HOME) 設置該組件爲Home Activity。
    CATEGORY_PREFERENCE: (android.intent.category.PREFERENCE) 設置該組件爲Preference。 
    CATEGORY_LAUNCHER: (android.intent.category.LAUNCHER) 設置該組件爲在當前應用程序啓動器中優先級最高的Activity,通常與入口ACTION_MAIN配合使用。
    CATEGORY_BROWSABLE: (android.intent.category.BROWSABLE) 設置該組件可以使用瀏覽器啓動。
    CATEGORY_BROWSABLE:設置該組件可以使用瀏覽器啓動。 
    CATEGORY_GADGET:設置該組件可以內嵌到另外的Activity中。

     

  • Data:Data通常是URI格式定義的操作數據。例如:tel:// 。通過setData()方法設置。
    在intent-filter中指定data屬性的實際目的是:要求接收的Intent中的data必須符合intent-filter中指定的data屬性,這樣達到反向限定Intent的作用
    			// 打開網頁
    			intent = new Intent(Intent.ACTION_VIEW);
    			intent.setData(Uri.parse("http://www.baidu.com"));
    			startActivity(intent);
    			// 打電話
    			intent = new Intent(Intent.ACTION_VIEW);
    			intent.setData(Uri.parse("tel:183****8515"));
    			startActivity(intent);
            
                常用屬性
                tel://:號碼數據格式,後跟電話號碼。 
                mailto://:郵件數據格式,後跟郵件收件人地址。
                smsto://:短息數據格式,後跟短信接收號碼。  
                content://:內容數據格式,後跟需要讀取的內容。  
                file://:文件數據格式,後跟文件路徑。  
                market://search?q=pname:pkgname:市場數據格式,在Google Market裏搜索包名爲pkgname的應用。  
                geo://latitude, longitude:經緯數據格式,在地圖上顯示經緯度所指定的位置。

     

  • Extras:Extras屬性主要用於傳遞目標組件所需要的額外的數據。通過putExtras()方法設置。Extra可以傳遞基本類型,String類型以及實現了Serializable或者Parcelable接口的類。
    通過intent.putExtra(鍵, 值)的形式在多個Activity之間進行數據交換

    常用屬性
    EXTRA_BCC:存放郵件密送人地址的字符串數組。 
    EXTRA_CC:存放郵件抄送人地址的字符串數組。
    EXTRA_EMAIL:存放郵件地址的字符串數組。 
    EXTRA_SUBJECT:存放郵件主題字符串。 
    EXTRA_TEXT:存放郵件內容。 
    EXTRA_KEY_EVENT:以KeyEvent對象方式存放觸發Intent的按鍵。  
    EXTRA_PHONE_NUMBER:存放調用ACTION_CALL時的電話號碼。 

     

  • Type:Type是對Data的類型作進一步的說明。Type在manifest中的設置同樣也在<data>標籤中,是data的mimeType屬性。
    mimeType包括許多文件類型,包括圖片、視頻、音頻等等,每種類型下也可以包含多種文件格式,以下舉例部分:
     

    text/plain 純文本
    image/gif image/gif
    image/jpeg jpeg圖像
    video/mpeg MPEG動畫
    audio/mp3 mp3音樂

    也可以不指定具體文件格式,只指定文件類型:
     

    image/* 指定類型爲image的所有文件
    audio/* 指定類型爲audio的所有文件
    video/* 指定類型爲video的所有文件
    播放視頻:
    Intent intent = new Intent(); 
    Uri uri = Uri.parse("file:///sdcard/media.mp4"); 
    intent.setAction(Intent.ACTION_VIEW);
    intent.setDataAndType(uri, "video/*"); 
    startActivity(intent);

3.Activity的生命週期

  • 運行狀態:可見也可操作
  • 暫停狀態:可見但不可操作
  • 停止狀態:不可見,但對象存在
  • 死亡狀態:對象不存在

onCreate:在首次創建 Activity 時調用。系統向此方法傳遞一個 Bundle 對象,其中包含 Activity 的上一狀態,不過前提是捕獲了該狀態,而後會調用onStart方法。(可以在此方法中執行所有正常的靜態設置 ,比如:創建視圖、將數據綁定到列表等等。)
onStart:在 Activity 即將對用戶可見之前調用。而後如果Activity轉入了前臺就會調用onResume方法。 如果此時直接屏幕熄滅或者用戶按下home鍵則會直接調用onStop方法,當然這種情況比較極端。
onResume:在 Activity 即將開始與用戶進行交互之前調用。 此時,Activity 處於 Activity 堆棧的頂層,並具有用戶輸入焦點。當跳轉另一個Activity,或者退出當前Activity後會調用onPause方法。
onPause:在系統即將開始繼續另一個 Activity 時調用。 此方法通常用於確認對持久性數據的未保存更改、停止動畫以及其他可能消耗 CPU 的內容,諸如此類。 它應該非常迅速地執行所需操作,因爲它返回後,下一個 Activity 才能繼續執行,所以不能執行耗時操作。而後正常情況下會調用onStop方法。但是有一種極端情況,就是如果這個時候快速讓 當前Activity 返回前臺,則會調用onResume方法。
onStop:在 Activity 對用戶不再可見時調用。如果 Activity 被銷燬,或另一個 Activity(一個現有 Activity 或新 Activity)繼續執行並將其覆蓋,就會調用此方法。而後如果 Activity 恢復與用戶的交互,則會調用 onRestart 方法,如果 Activity 被銷燬,則會調用onDestroy方法。
onRestart:在Activity被停止後再次啓動時調用(即屏幕熄滅後再次回到app,按下home鍵後再次回到app),而後會調用onStart方法。
onDestroy:在 Activity 被銷燬前調用,這是 Activity 收到的最後調用。 當 Activity 結束(對 Activity 調用了 finish 方法),或系統爲節省空間而暫時銷燬該 Activity 實例時,可能會調用它。 你可以通過 isFinishing 方法區分這兩種情形

問題一:從A-Activity跳轉到B-Activity生命週期是?

A_onCreate-->A_onStart-->A_onResume-->A_onPause-->B_onCreate-->B_onStart-->B_onResume-->A_onStop

問題二:從A-Activity跳轉到B-Activity,然後再按Home的生命週期是?

A_onCreate-->A_onStart-->A_onResume-->A_onPause-->B_onCreate-->B_onStart-->B_onResume-->A_onStop-->B_onPause-->B_onStop

問題三:從A-Activity跳轉到B-Activity,再返回到A-Activity

A_onCreate-->A_onStart-->A_onResume-->A_onPause-->B_onCreate-->B_onStart-->B_onResume-->A_onStop-->B_onPause-->A_onRestart--->A_onstart--->A_onResume-->B_onStop--->B_onDestroy

lauchMode 啓動模式

1. standard  默認標準的啓動模式,每次startActivity都是創建一個新的activity的實例。

              應用場景: 適用於絕大大數情況

2. singleTop  單一頂部,如果要開啓的activity在任務棧的頂部已經存在,就不會創建新的實例,

              而是調用 onNewIntent() 方法。

              應用場景: 瀏覽器的書籤。 避免棧頂的activity被重複的創建,解決用戶體驗問題。

              例如,某個新聞客戶端的新聞內容頁面,如果收到10個新聞推送,每次都打開一個新聞內容頁面是很煩人的。

3. singleTask 單一任務棧 , activity只會在任務棧裏面存在一個實例。如果要激活的activity,在任務棧裏面已經存在,就不會創建新的activity,而是複用這個已經存在的activity,調用 onNewIntent() 方法,並且清空這個activity任務棧上面所有的activity

              應用場景:瀏覽器的書籤, 整個任務棧只有一個實例,節約內存和cpu的目的

              注意: activity還是運行在當前應用程序的任務棧裏面的。不會創建新的任務棧。

4. singleInstance  單態 單例模式

              單一實例,整個手機操作系統裏面只有一個實例存在。不同的應用去打開這個activity 共享公用的同一個activity。

              他會運行在自己單獨,獨立的任務棧裏面,並且任務棧裏面只有他一個實例存在。

              應用場景:呼叫來電界面 InCallScreen、手機聯繫人界面 鬧鐘

瞭解更多

Intent 能傳遞多大 Size 的數據?(附阿里答案)

Activity面試你所需知道的一切

2019 Android 高級面試題總結

Activity生命週期
Activity 的 36 個問題,你還記得幾個?

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章