Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android四大基本組件之Activity與BroadcastReceive廣播接收器

Android四大基本組件之Activity與BroadcastReceive廣播接收器

編輯:關於Android編程

Android四大基本組件分別是Activity,Service服務,Content Provider內容提供者,BroadcastReceiver廣播接收器。

一、Activity

(1)應用程序中,一個Activity通常就是一個單獨的屏幕,它上面可以顯示一些控件也可以監聽並處理用戶的事件做出響應。

(2)Activity之間通過Intent進行通信。在Intent 的描述結構中,有兩個最重要的部分:動作和動作對應的數據。

(3)典型的動作類型有:M AIN(activity的門戶)、VIEW、PICK、EDIT 等。而動作對應的數據則以URI 的形式進行表示。例如:要查看一個人的聯系方式,你需要創建一個動作類型為VIEW 的intent,以及一個表示這個人的URI。

(4)與之有關系的一個類叫IntentFilter。相對於intent 是一個有效的做某事的請求,一個intentfilter 則用於描述一個activity(或者IntentReceiver)能夠操作哪些intent。一個activity 如果要顯示一個人的聯系方式時,需要聲明一個IntentFilter,這個IntentFilter 要知道怎麼去處理VIEW 動作和表示一個人的URI。IntentFilter 需要在AndroidManifest.xml 中定義。通過解析各種intent,從一個屏幕導航到另一個屏幕是很簡單的。當向前導航時,activity 將會調用startActivity(Intent myIntent)方法。然後,系統會在所有安裝的應用程序中定義的IntentFilter 中查找,找到最匹配myIntent 的Intent 對應的activity。新的activity 接收到myIntent 的通知後,開始運行。當startActivity 方法被調用將觸發解析myIntent 的動作,這個機制提供了兩個關鍵好處:

A、Activities 能夠重復利用從其它組件中以Intent 的形式產生的一個請求;

B、Activities 可以在任何時候被一個具有相同IntentFilter 的新的Activity 取代。

(5)AndroidManifest文件中含有如下過濾器的Activity組件為默認啟動類當程序啟動時系統自動調用它


     
     

(6)Activty的生命周期的也就是它所在進程的生命周期。
這裡寫圖片描述

1).一個Activity的啟動順序:

onCreate()——>onStart()——>onResume()

2).當另一個Activity啟動時:

第一個Activity onPause()——>第二個Activity onCreate()——>onStart()——>onResume()
——>第一個Activity onStop()

3).當返回到第一個Activity時:

第二個Activity onPause() ——> 第一個Activity onRestart()——>onStart()——>onResume()
——>第二個Activity onStop()——>onDestroy()

4).一個Activity的銷毀順序:

(情況一)onPause()——>
(情況二)onPause()——>onStop()——>
(情況三)onPause()——>onStop()——>onDestroy()

  每一個活動( Activity )都處於某一個狀態,對於開發者來說,是無法控制其應用程序處於某一個狀態的,這些均由系統來完成。

  但是當一個活動的狀態發生改變的時候,開發者可以通過調用 onXX() 的方法獲取到相關的通知信息。

  在實現 Activity 類的時候,通過覆蓋( override )這些方法即可在你需要處理的時候來調用。
  一、 onCreate :當活動第一次啟動的時候,觸發該方法,可以在此時完成活動的初始化工作。
onCreate 方法有一個參數,該參數可以為空( null ),也可以是之前調用 onSaveInstanceState ()方法保存的狀態信息。
二、 onStart :該方法的觸發表示所屬活動將被展現給用戶。
三、 onResume :當一個活動和用戶發生交互的時候,觸發該方法。
四、 onPause :當一個正在前台運行的活動因為其他的活動需要前台運行而轉入後台運行的時候,觸發該方法。這時候需要將活動的狀態持久化,比如正在編輯的數據庫記錄等。
五、 onStop :當一個活動不再需要展示給用戶的時候,觸發該方法。如果內存緊張,系統會直接結束這個活動,而不會觸發 onStop 方法。 所以保存狀態信息是應該在onPause時做,而不是onStop時做。活動如果沒有在前台運行,都將被停止或者Linux管理進程為了給新的活動預留足夠的存儲空間而隨時結束這些活動。因此對於開發者來說,在設計應用程序的時候,必須時刻牢記這一原則。在一些情況下,onPause方法或許是活動觸發的最後的方法,因此開發者需要在這個時候保存需要保存的信息。
六、onRestart :當處於停止狀態的活動需要再次展現給用戶的時候,觸發該方法。
七、 onDestroy :當活動銷毀的時候,觸發該方法。和 onStop 方法一樣,如果內存緊張,系統會直接結束這個活動而不會觸發該方法。
· onSaveInstanceState :系統調用該方法,允許活動保存之前的狀態,比如說在一串字符串中的光標所處的位置等。
通常情況下,開發者不需要重寫覆蓋該方法,在默認的實現中,已經提供了自動保存活動所涉及到的用戶界面組件的所有狀態信息。

  Activity棧

  上面提到開發者是無法控制Activity的狀態的,那Activity的狀態又是按照何種邏輯來運作的呢?這就要知道 Activity 棧。
  每個Activity的狀態是由它在Activity棧(是一個後進先出LIFO,包含所有正在運行Activity的隊列)中的位置決定的。
  當一個新的Activity啟動時,當前的活動的Activity將會移到Activity棧的頂部。
  如果用戶使用後退按鈕返回的話,或者前台的Activity結束,活動的Activity就會被移出棧消亡,而在棧上的上一個活動的Activity將會移上來並變為活動狀態。如下圖所示:
這裡寫圖片描述vcq9xvS2r9K7uPbM+Neqtb3UrcC0xLO49kFjdGl2aXR5yrXA/aGjPGJyIC8+DQqhoaGh1NphbmRyb2lkwO+jrNPQNNbWYWN0aXZpdHm1xMb0tq/Eo8q9o6y31rHwzqqjujxiciAvPg0KoaGhoSZtaWRkb3Q7c3RhbmRhcmQ6ILHq17zEo8q9o6zSu7X308NzdGFydEFjdGl2aXR5KCm3vbeovs274bL6yfrSu7j20MK1xMq1wP2hozxiciAvPg0KoaGhoSZtaWRkb3Q7c2luZ2xlVG9wOiDI57n70tG+rdPQ0ru49sq1wP3Ou9PaQWN0aXZpdHnVu7XEtqWyv8qxo6y+zbK7svrJ+tDCtcTKtcD9o6y2+Na7yse199PDQWN0aXZpdHnW0LXEbmV3SW5zdGFuY2UoKbe9t6iho8jnufuyu86709rVu7alo6y74bL6yfrSu7j20MK1xMq1wP2hozxiciAvPg0KoaGhoSZtaWRkb3Q7c2luZ2xlVGFzazogu+HU2tK7uPbQwrXEdGFza9bQsvrJ+tXiuPbKtcD9o6zS1Lrzw7+0zrX308O2vLvhyrnTw9XiuPajrLK7u+HIpbL6yfrQwrXEyrXA/cHLoaM8YnIgLz4NCqGhoaEmbWlkZG90O3NpbmdsZUluc3RhbmNlOiDV4rj2uPpzaW5nbGVUYXNru/mxvsnPysfSu9H5o6zWu9PQ0ru49sf4sfCjutTa1eK49sSjyr3PwrXEQWN0aXZpdHnKtcD9y/m0prXEdGFza9bQo6zWu8Tc09DV4rj2YWN0aXZpdHnKtcD9o6yyu8Tc09DG5Mv7tcTKtcD9oaM8YnIgLz4NCqGhoaHV4tCpxvS2r8Sjyr2/ydLU1Nq5psTcx+W1pc7EvP5BbmRyb2lkTWFuaWZlc3QueG1s1tC9+NDQyejWw6Os1tC1xGxhdW5jaE1vZGXK9NDUoaM8YnIgLz4NCqGhoaHP4LnYtcS0+sLr1tDSstPQ0rvQqbHq1r6/ydLUyrnTwyyxyMjnztLDx8/r1rvG9NPD0ru49sq1wP0s1PK/ydLUyrnTwyBJbnRlbnQuRkxBR19BQ1RJVklUWV9SRU9SREVSX1RPX0ZST05UILHq1r6jrNXiuPax6ta+se3KvqO6yOe5+9XiuPZhY3Rpdml0edLRvq3G9LavwcujrL7Nsruy+sn60MK1xGFjdGl2aXR5o6y2+Na7ysew0dXiuPZhY3Rpdml0ecq1wP2807W91bu2pcC0vs2/ydLUwcuhozxiciAvPg0KoaGhoTwvcD4NCjxwcmUgY2xhc3M9"brush:java;"> Intent intent = new Intent(ReorderFour.this, ReorderTwo.class);   intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);   startActivity(intent);

Activity的加載模式受啟動Activity的Intent對象中設置的Flag和manifest文件中Activity的元素的特性值交互控制。
  下面是影響加載模式的一些特性
  核心的Intent Flag有:
  FLAG_ACTIVITY_NEW_TASK
  FLAG_ACTIVITY_CLEAR_TOP
  FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
  FLAG_ACTIVITY_SINGLE_TOP

核心的特性有:
  taskAffinity
  launchMode
  allowTaskReparenting
  clearTaskOnLaunch
  alwaysRetainTaskState
  finishOnTaskLaunch

 四種加載模式的區別
  所屬task的區別
  一般情況下,“standard”和”singleTop”的activity的目標task,和收到的Intent的發送者在同一個task內,就相當於誰調用它,它就跟誰在同一個Task中。
  除非Intent包括參數FLAG_ACTIVITY_NEW_TASK。如果提供了FLAG_ACTIVITY_NEW_TASK參數,會啟動到別的task裡。
  “singleTask”和”singleInstance” 總是把要啟動的activity作為一個task的根元素,他們不會被啟動到一個其他task裡。
  是否允許多個實例
  “standard”和”singleTop”可以被實例化多次,並且是可以存在於不同的task中;這種實例化時一個task可以包括一個activity的多個實例;
  “singleTask”和”singleInstance”則限制只生成一個實例,並且是task的根元素。
  singleTop 要求如果創建intent的時候棧頂已經有要創建的Activity的實例,則將intent發送給該實例,而不創建新的實例。
  是否允許其它activity存在於本task內
  “singleInstance”獨占一個task,其它activity不能存在那個task裡;
  如果它啟動了一個新的activity,不管新的activity的launch mode 如何,新的activity都將會到別的task裡運行(如同加了FLAG_ACTIVITY_NEW_TASK參數)。
  而另外三種模式,則可以和其它activity共存。
  是否每次都生成新實例
  “standard”對於每一個啟動Intent都會生成一個activity的新實例;
  “singleTop”的activity如果在task的棧頂的話,則不生成新的該activity的實例,直接使用棧頂的實例,否則,生成該activity的實例。
  比如:
  現在task棧元素為A-B-C-D(D在棧頂),這時候給D發一個啟動intent,如果D是 “standard”的,則生成D的一個新實例,棧變為A-B-C-D-D。
  如果D是singleTop的話,則不會生產D的新實例,棧狀態仍為A-B-C-D
  如果這時候給B發Intent的話,不管B的launchmode是”standard” 還是 “singleTop” ,都會生成B的新實例,棧狀態變為A-B-C-D-B。
  “singleInstance”是其所在棧的唯一activity,它會每次都被重用。
  “singleTask” 如果在棧頂,則接受intent,否則,該intent會被丟棄,但是該task仍會回到前台。 當已經存在的activity實例處理新的intent時候,會調用onNewIntent()方法,如果收到intent生成一個activity實例,那麼用戶可以通過back鍵回到上一個狀態;如果是已經存在的一個activity來處理這個intent的話,用戶不能通過按back鍵返回到這之前的狀態。

二、BroadcastReceive廣播接收器

你的應用可以使用它對外部事件進行過濾只對感興趣的外部事件(如當電話呼入時,或者數據網絡可用時)進行接收並做出響應。廣播接收器沒有用戶界面。然而,它們可以啟動一個activity或serice 來響應它們收到的信息,或者用NotificationManager 來通知用戶。通知可以用很多種方式來吸引用戶的注意力──閃動背燈、震動、播放聲音等。一般來說是在狀態欄上放一個持久的圖標,用戶可以打開它並獲取消息。

廣播類型:

普通廣播,通過Context.sendBroadcast(Intent myIntent)發送的

有序廣播,通過Context.sendOrderedBroadcast(intent, receiverPermission)發送的,該方法第2個參數決定該廣播的級別,級別數值是在 -1000 到 1000 之間 , 值越大 , 發送的優先級越高;廣播接收者接收廣播時的級別級別(可通過intentfilter中的priority進行設置設為2147483647時優先級最高),同級別接收的先後是隨機的, 再到級別低的收到廣播,高級別的或同級別先接收到廣播的可以通過abortBroadcast()方法截斷廣播使其他的接收者無法收到該廣播,還有其他構造函數

異步廣播,通過Context.sendStickyBroadcast(Intent myIntent)發送的,還有sendStickyOrderedBroadcast(intent, resultReceiver, scheduler, initialCode, initialData, initialExtras)方法,該方法具有有序廣播的特性也有異步廣播的特性;發送異步廣播要: 權限,接收並處理完Intent後,廣播依然存在,直到你調用removeStickyBroadcast(intent)主動把它去掉

注意:發送廣播時的intent參數與Contex.startActivity()啟動起來的Intent不同,前者可以被多個訂閱它的廣播接收器調用,後者只能被一個(Activity或service)調用

監聽廣播Intent步驟:

1> 寫一個繼承BroadCastReceiver的類,重寫onReceive()方法,廣播接收器僅在它執行這個方法時處於活躍狀態。當onReceive()返回後,它即為失活狀態,注意:為了保證用戶交互過程的流暢,一些費時的操作要放到線程裡,如類名SMSBroadcastReceiver

2> 注冊該廣播接收者,注冊有兩種方法程序動態注冊和AndroidManifest文件中進行靜態注冊(可理解為系統中注冊)如下:

    靜態注冊,注冊的廣播,下面的priority表示接收廣播的級別"2147483647"為最高優先級

  
    
  

動態注冊,一般在Activity可交互時onResume()內注冊BroadcastReceiver

IntentFilter intentFilter=new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
registerReceiver(mBatteryInfoReceiver ,intentFilter);

//反注冊
unregisterReceiver(receiver);

注意:

1.生命周期只有十秒左右,如果在 onReceive() 內做超過十秒內的事情,就會報ANR(Application No Response) 程序無響應的錯誤信息,如果需要完成一項比較耗時的工作 , 應該通過發送 Intent 給 Service, 由Service 來完成 . 這裡不能使用子線程來解決 , 因為 BroadcastReceiver 的生命周期很短 , 子線程可能還沒有結束BroadcastReceiver 就先結束了 .BroadcastReceiver 一旦結束 , 此時 BroadcastReceiver 的所在進程很容易在系統需要內存時被優先殺死 , 因為它屬於空進程 ( 沒有任何活動組件的進程 ). 如果它的宿主進程被殺死 , 那麼正在工作的子線程也會被殺死 . 所以采用子線程來解決是不可靠的

動態注冊廣播接收器還有一個特點,就是當用來注冊的Activity關掉後,廣播也就失效了。靜態注冊無需擔憂廣播接收器是否被關閉,只要設備是開啟狀態,廣播接收器也是打開著的。也就是說哪怕app本身未啟動,該app訂閱的廣播在觸發時也會對它起作用

系統常見廣播Intent,如開機啟動、電池電量變化、時間改變等廣播

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved