Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android四大組件詳解

android四大組件詳解

編輯:關於Android編程

android四大組件分別是activity,service,content provider,broadcast receiver。

一,activity詳解

1,概述

(1)一個Activity通常就是一個單獨的屏幕(窗口)。

(2)Activity之間通過Intent進行通信。

(3)android應用中每一個Activity都必須要在AndroidManifest.xml配置文件中聲明,否則系統將不識別也不執行該Activity

2,生命周期

ONcreate----》創建
onstart-----》界面可見
onResume----》界面可以獲取焦點並且可以和用戶交互
onpause-----》界面暫停,界面失去焦點
onstop -----》界面停止,不可見
ondestory---》銷毀
onrestart---》重新啟動

方法

描述

完成後可殺掉?

下一個

onCreate()

當activity被創建時調用。這是做一般的靜態初始化的地方,比如創建界面,把數據綁定到列表,等等之類。這個方法會被傳入一個Bundle對像,它包含了activity的上一次(關閉時)的狀態(如果這個狀態可以得到)。此方法後面永遠跟著onStart()。

onStart()

onRestart()

在停止後被調用,但不是停止後馬上調用,而是在再次開始前調用,也就是在再次調用onStart()之前立即調用。

onStart()

onStart()

當activity變成可見後立即調用它。如果activity成為最上層,則調用onResume(),如果完全被摭蓋,就調用onStop()。

onResume()或onStop()

onResume()

當activity處於最上層時,立即調用此方法。此時activity獲得輸入焦點。後面跟著onPause()。

onPause()

onPause()

當另一個activity要進入Pause狀態時調用此方法。這個方法一般是用來提交那些發生改變的永久化的數據們,停止動畫和其它消耗CPU的玩意們。這些工作必須以最快的速度完成,因為在這個方法返回之前,另一個activity就不能進入resume狀態。當它又回到最上層時,後面跟著onResume(),當它被完全摭蓋時,後面跟著onStop()。

onResume()

or

onStop()

onStop()

當activity被完全摭蓋時被調用。當activity要銷毀時或被其它activity完全摭蓋時都會發生。如果這個activity又回到最上層,則後面跟著onRestart(),如果它逝去了,則跟著onDestroy()。

onRestart()

or

onDestroy()

onDestroy()

在activity銷毀之前被調用。這是activity能收到的最後一個調用。調用的原因可能是別人在這個activity上調用了finish(),也可能是系統為了更多的內存空間而把它所在的進程處死了。在這個方法中,可以調用isFinishing()來判斷自己屬於哪一種死法。

nothing


 

兩個最重要的方法是:

 

onCreate()--這個是必須實現的函數,在其中做初始化工作。記住:你必須在此函數中調用setContentView()函數的設置Activity的界面。

onPause()--這個雖然很重要,但不是要必須實現的。此函數在用戶離開Activity時被調用(這一般並不表示Activity要被銷毀了)。在這個函數中,你一般需要提交那些需保存狀態的數據(因為用戶可能不再返回到這個Activity)。

其它回調方法視情況實現。

一個activity的啟動順序:

onCreate()---->onStart()----->onResume()

當另一個Activity啟動時:

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

當返回到第一個Activity時:

第二個Activity onPause()---->第一個Activity onRestart()----->onstart()----->onResume()------>第二個Activity onstop()-----.ondestroy()

 

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

但是當一個活動的狀態發生改變的時候,開發者可以通過調用onXX()的方法獲取相關的通知信息。在實現Activity類的時候,通過重寫這些方法即可在你需要處理的時候來調用。

onCreate:當活動第一次啟動的時候,觸發該方法,可以在此時完成活動的初始化工作。onCreate方法有一個參數,該參數可以為空,也可以是之前調用onSaveInstanceState()方法保存的狀態信息。

 

onStart:該方法的觸發表示所屬活動將被展現給用戶。

 

 

onResume:當一個活動和用戶發生交互的時候,觸發該方法。

 

 

onPause:當一個正在前台運行的活動因為其他的活動需要前台運行而轉入後台運行的時候觸發該方法。這時候需要將活動的狀態持久化,比如正在編輯的數據庫記錄等。

 

 

onStop :當一個活動活動不再需要展示給用戶的時候,觸發該方法,如果內存緊張,系統會直接結束這個活動,而不會觸發onStop方法。所以保存狀態信息在onPause時做,而不是onStop時做。活動如果沒有在前台運行,都將被停止或者linux管理進程為了給新的活動預留足夠的存儲空間而隨時結束這些活動。因此對於開發者來說,在設計應用程序的時候,必須時刻牢記這一原則。在一些情況下,onPause方法或許是活動觸發的最後方法,因此開發者需要在這個時候保存需要保存的信息。

 

 

onRestart:當處於停止狀態的活動需要再次展現給用戶的時候,觸發該方法。

 

 

onDestroy:當活動銷毀的時候,觸發該方法。和onStop方法一樣,如果內存緊張,系統會直接結束這個活動而不會觸發該方法。

 

 

3,activity的四種加載模式

在android的多activity開發中,activity之間的跳轉可能需要多種方式,有時是普通的生成一個新實例,有時西希望跳轉到原來某個activity實例,而不是生成大量的重復activity。載模式便是決定以哪種方式啟動一個跳轉到原來某個Activity實例。

 

(1)standard:標准模式,一調用startActivity方法就會產生一個新的實例。

(2)singleTop:如果已經有一個實例位於activity棧的頂部時,就不產生新的實例,而只是調用Activity中的newInstance()方法。如果不位於棧頂,會產生一個新的實例。

(3)singleTask:會在一個新的task中產生這個實例,以後每次調用都會使用這個,不會去產生新的實例了。

(4)singleInstance:這個跟singleTask基本上是一樣,只有一個區別:在這個模式下的Activity實例所處的task中,只能有這個activity實例,不能有其他的實例。

這些啟動模式可以在功能清單文件AndroidManifest.xml中進行設置launchMode屬性

 

 

二,service詳解

1,概述

(1)service用於在後台完成用戶指定的操作。service分為兩種:

(a)started(啟動):當應用程序組件(如activity)調用startService()方法啟動服務時,服務處於started狀態。

(b)bound(綁定):當應用程序組件調用bindService()方法綁定到服務時,服務處於bound狀態。

(2)startService()與bindService()的區別:

(a)started service(啟動服務)是由其他組件調用startService()方法啟動的,這導致服務的onStartCommand()方法被調用。當服務是started狀態時,其生命周期與啟動它的組件無關,並且可以後台無限期運行,即使啟動服務的組件已經被銷毀。因此,服務需要在完成任務後調用stopSelf()方法停止,或者有其他組件調用stopService()方法停止。

(b)使用bindService()方法啟用服務,調用者與服務綁定在了一起,調用者一但退出,服務也就終止,大有”不求同時生,必須同時死“的特點。

(3)開發人員需要在應用程序配置文件中聲明全部的service,使用標簽。

(4)Service通常位於後台運行,他一般不需要與用戶交互,因此service組件沒有圖形用戶界面。service組建需要繼承service基類。service組件通常用於為其他組件提供後台服務或監控其他組件的運行狀態。

 

 

2.Service的生命周期

onCreate  onStart  onDestroy  onBind

1). 被啟動的服務的生命周期:如果一個Service被某個Activity 調用 Context.startService 方法啟動,那麼不管是否有Activity使用bindService綁定或unbindService解除綁定到該Service,該Service都在後台運行。如果一個Service被startService 方法多次啟動,那麼onCreate方法只會調用一次,onStart將會被調用多次(對應調用startService的次數),並且系統只會創建Service的一個實例(因此你應該知道只需要一次stopService調用)。該Service將會一直在後台運行,而不管對應程序的Activity是否在運行,直到被調用stopService,或自身的stopSelf方法。當然如果系統資源不足,android系統也可能結束服務。

2). 被綁定的服務的生命周期:如果一個Service被某個Activity 調用 Context.bindService 方法綁定啟動,不管調用 bindService 調用幾次,onCreate方法都只會調用一次,同時onStart方法始終不會被調用。當連接建立之後,Service將會一直運行,除非調用Context.unbindService 斷開連接或者之前調用bindService 的 Context 不存在了(如Activity被finish的時候),系統將會自動停止Service,對應onDestroy將被調用。

3). 被啟動又被綁定的服務的生命周期:如果一個Service又被啟動又被綁定,則該Service將會一直在後台運行。並且不管如何調用,onCreate始終只會調用一次,對應startService調用多少次,Service的onStart便會調用多少次。調用unbindService將不會停止Service,而必須調用 stopService 或 Service的 stopSelf 來停止服務。

4). 當服務被停止時清除服務:當一個Service被終止(1、調用stopService;2、調用stopSelf;3、不再有綁定的連接(沒有被啟動))時,onDestroy方法將會被調用,在這裡你應當做一些清除工作,如停止在Service中創建並運行的線程。

特別注意:

1、你應當知道在調用 bindService 綁定到Service的時候,你就應當保證在某處調用 unbindService 解除綁定(盡管 Activity 被 finish 的時候綁定會自      動解除,並且Service會自動停止);

2、你應當注意 使用 startService 啟動服務之後,一定要使用 stopService停止服務,不管你是否使用bindService;

3、同時使用 startService 與 bindService 要注意到,Service 的終止,需要unbindService與stopService同時調用,才能終止 Service,不管 startService 與 bindService 的調用順序,如果先調用 unbindService 此時服務不會自動終止,再調用 stopService 之後服務才會停止,如果先調用 stopService 此時服務也不會終止,而再調用 unbindService 或者 之前調用 bindService 的 Context 不存在了(如Activity 被 finish 的時候)之後服務才會自動停止;

4、當在旋轉手機屏幕的時候,當手機屏幕在“橫”“豎”變換時,此時如果你的 Activity 如果會自動旋轉的話,旋轉其實是 Activity 的重新創建,因此旋轉之前的使用 bindService 建立的連接便會斷開(Context 不存在了),對應服務的生命周期與上述相同。

5、在 sdk 2.0 及其以後的版本中,對應的 onStart 已經被否決變為了 onStartCommand,不過之前的 onStart 任然有效。這意味著,如果你開發的應用程序用的 sdk 為 2.0 及其以後的版本,那麼你應當使用 onStartCommand 而不是 onStart。


 

三、Broadcast Receiver詳解


  BroadcastReceiver 用於異步接收廣播Intent。主要有兩大類,用於接收廣播的:

  ·正常廣播 Normal broadcasts(用 Context.sendBroadcast()發送)是完全異步的。它們都運行在一個未定義的順序,通常是在同一時間。這樣會更有效,但意味著receiver不能包含所要使用的結果或中止的API。

  ·有序廣播 Ordered broadcasts(用 Context.sendOrderedBroadcast()發送)每次被發送到一個receiver。所謂有序,就是每個receiver執行後可以傳播到下一個receiver,也可以完全中止傳播--不傳播給其他receiver。 而receiver運行的順序可以通過matched intent-filter 裡面的android:priority來控制,當priority優先級相同的時候,Receiver以任意的順序運行。

  要注意的是,即使是Normal broadcasts,系統在某些情況下可能會恢復到一次傳播給一個receiver。 特別是receiver可能需要創建一個進程,為了避免系統超載,只能一次運行一個receiver。

  Broadcast Receiver 並沒有提供可視化的界面來顯示廣播信息。可以使用Notification和Notification Manager來實現可視化的信息的界面,顯示廣播信息的內容,圖標及震動信息。

  生命周期

  一個BroadcastReceiver 對象只有在被調用onReceive(Context, Intent)的才有效的,當從該函數返回後,該對象就無效的了,結束生命周期。

  因此從這個特征可以看出,在所調用的onReceive(Context, Intent)函數裡,不能有過於耗時的操作,不能使用線程來執行。對於耗時的操作,請start service來完成。因為當得到其他異步操作所返回的結果時,BroadcastReceiver 可能已經無效了。

  發送廣播

  事件的廣播比較簡單,構建Intent對象,可調用sendBroadcast(Intent)方法將廣播發出。另外還有sendOrderedBroadcast(),sendStickyBroadcast()等方法,請查閱API Doc。

  1.new Intent with action name

  Intent intent = new Intent(String action);

  或者 只是new Intent, 然後

  intent.setAction(String action);

  2.set data等准備好了後,in activity,

  sendBroadcast(Intent); // 發送廣播

  接收廣播

  通過定義一個繼承BroadcastReceiver類來實現,繼承該類後覆蓋其onReceiver方法,並在該方法中響應事件。

 

注冊Receiver

  注冊有兩種方式:

  1. 靜態方式,在AndroidManifest.xml的application裡面定義receiver並設置要接收的action。
 

  1.   
  2.  
  3.   
  4.  
  5.   
  6.  
  7.   
  8.  
  9.   
復制代碼 2.動態方式, 在activity裡面調用函數來注冊,和靜態的內容差不多。一個形參是receiver,另一個是IntentFilter,其中裡面是要接收的action。
  1. public class HelloDemo extends Activity {
  2. private BroadcastReceiver receiver;
  3.  
  4. @Override
  5. protected void onStart() {
  6. super.onStart();
  7.  
  8. receiver = new CallReceiver();
  9. registerReceiver(receiver, new IntentFilter("android.intent.action.PHONE_STATE"));
  10. }
  11.  
  12. @Override
  13. protected void onStop() {
  14. unregisterReceiver(receiver);
  15. super.onStop();
  16. }
  17. }
  18.  
復制代碼   一個receiver可以接收多個action的,即可以有多個intent-filter,需要在onReceive裡面對intent.getAction(action name)進行判斷。

  個人推薦使用靜態注冊方式,由系統來管理receiver,而且程序裡的所有receiver,可以在xml裡面一目了然。而動態注冊方式,隱藏在代碼中,比較難發現。

  而且動態注冊,需要特別注意的是,在退出程序前要記得調用Context.unregisterReceiver()方法。一般在activity的onStart()裡面進行注冊, onStop()裡面進行注銷。官方提醒,如果在Activity.onResume()裡面注冊了,就必須在Activity.onPause()注銷。

  Permission權限

  要接收某些action,需要在AndroidManifest.xml裡面添加相應的permission。例如接收SMS:

復制代碼   下面給出動態注冊的接收來電的廣播處理的CallReceiver的代碼:

  一種方式是直接讀取intent.getStringExtra("incoming_number")來獲取來電號碼:

  1. public class CallReceiver extends BroadcastReceiver {
  2.  
  3. @Override
  4. public void onReceive(Context context, Intent intent) {
  5. TelephonyManager teleManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
  6.  
  7. switch(teleManager.getCallState()){
  8. case TelephonyManager.CALL_STATE_RINGING: //響鈴
  9. Toast.makeText(context, "Ringing: " + intent.getStringExtra("incoming_number"), Toast.LENGTH_LONG).show();
  10. break;
  11. case TelephonyManager.CALL_STATE_OFFHOOK: //接聽
  12. Toast.makeText(context, "OffHook: " + intent.getStringExtra("incoming_number"), Toast.LENGTH_LONG).show();
  13. break;
  14. case TelephonyManager.CALL_STATE_IDLE: //掛斷
  15. Toast.makeText(m_context, "Idle: " + incomingNumber, Toast.LENGTH_LONG).show();
  16. break;
  17. }
  18. }
  19. }
  20.  
復制代碼   在運行時,發現除了響鈴時可以獲取來電號碼,接聽和掛斷都不能成功獲取的,顯示為null。

  另一種方式是通過PhoneStateListener的onCallStateChanged來監聽狀態的變化:

  1. public class CallReceiver extends BroadcastReceiver {
  2.  
  3. private Context m_context;
  4. @Override
  5. public void onReceive(Context context, Intent intent) {
  6. m_context = context;
  7. TelephonyManager teleManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
  8. teleManager.listen(new PhoneStateListener(){
  9.  
  10. @Override
  11. public void onCallStateChanged(int state, String incomingNumber) {
  12. switch(state){
  13. case TelephonyManager.CALL_STATE_RINGING: //響鈴
  14. Toast.makeText(m_context, "Ringing: " + incomingNumber, Toast.LENGTH_LONG)
  15. .show();
  16. break;
  17. case TelephonyManager.CALL_STATE_OFFHOOK: //接聽
  18. Toast.makeText(m_context, "OffHook: " + incomingNumber, Toast.LENGTH_LONG)
  19. .show();
  20. break;
  21. case TelephonyManager.CALL_STATE_IDLE: //掛斷
  22. Toast.makeText(m_context, "Idle: " + incomingNumber, Toast.LENGTH_LONG)
  23. .show();
  24. break;
  25. }
  26. }}, PhoneStateListener.LISTEN_CALL_STATE);
  27. }
  28. }
  29.  
復制代碼   運行時也發現incomingNumber在接聽和掛斷時獲取為blank。

  因為這裡監聽的是通話的狀態變化,所以這個receiver會被調用3次。

  監聽通話狀態需要加上權限:

復制代碼   ===========

  小結:

  1. 對於sendBroadCast的intent對象,需要設置其action name;

  2. 推薦使用顯式指明receiver,在配置文件AndroidManifest.xml指明;

  3. 一個receiver可以接收多個action;

  4. 每次接收廣播都會重新生成一個接收廣播的對象,再次調用onReceive;

  5. 在BroadCast 中盡量不要處理太多邏輯問題,建議復雜的邏輯交給Activity 或者 Service 去處理。

 

 

 

 

--------------------------------------------
四、Content Provider詳解

  ContentProvider(內容提供者)是Android中的四大組件之一。主要用於對外共享數據,也就是通過ContentProvider把應用中的數據共享給其他應用訪問,其他應用可以通過ContentProvider對指定應用中的數據進行操作。ContentProvider分為系統的和自定義的,系統的也就是例如聯系人,圖片等數據。

  android中對數據操作包含有:

  file, sqlite3, Preferences, ContectResolver與ContentProvider前三種數據操作方式都只是針對本應用內數據,程序不能通過這三種方法去操作別的應用內的數據。

  android中提供ContectResolver與ContentProvider來操作別的應用程序的數據。

  使用方式:

  一個應用實現ContentProvider來提供內容給別的應用來操作,

  一個應用通過ContentResolver來操作別的應用數據,當然在自己的應用中也可以。

  以下這段是Google Doc中對ContentProvider的大致概述:

  內容提供者將一些特定的應用程序數據供給其它應用程序使用。內容提供者繼承於ContentProvider 基類,為其它應用程序取用和存儲它管理的數據實現了一套標准方法。然而,應用程序並不直接調用這些方法,而是使用一個 ContentResolver 對象,調用它的方法作為替代。ContentResolver可以與任意內容提供者進行會話,與其合作來對所有相關交互通訊進行管理。

  1.ContentProvider

  Android提供了一些主要數據類型的ContentProvider,比如音頻、視頻、圖片和私人通訊錄等。可在android.provider包下面找到一些Android提供的ContentProvider。通過獲得這些ContentProvider可以查詢它們包含的數據,當然前提是已獲得適當的讀取權限。

  主要方法:

  public boolean onCreate() 在創建ContentProvider時調用

  public Cursor query(Uri, String[], String, String[], String) 用於查詢指定Uri的ContentProvider,返回一個Cursor

  public Uri insert(Uri, ContentValues) 用於添加數據到指定Uri的ContentProvider中

  public int update(Uri, ContentValues, String, String[]) 用於更新指定Uri的ContentProvider中的數據

  public int delete(Uri, String, String[]) 用於從指定Uri的ContentProvider中刪除數據

  public String getType(Uri) 用於返回指定的Uri中的數據的MIME類型

  *如果操作的數據屬於集合類型,那麼MIME類型字符串應該以vnd.android.cursor.dir/開頭。

  例如:要得到所有person記錄的Uri為content://contacts/person,那麼返回的MIME類型字符串為"vnd.android.cursor.dir/person"。

  *如果要操作的數據屬於非集合類型數據,那麼MIME類型字符串應該以vnd.android.cursor.item/開頭。

  例如:要得到id為10的person記錄的Uri為content://contacts/person/10,那麼返回的MIME類型字符串應為"vnd.android.cursor.item/person"。

  2.ContentResolver

  當外部應用需要對ContentProvider中的數據進行添加、刪除、修改和查詢操作時,可以使用ContentResolver類來完成,要獲取ContentResolver對象,可以使用Context提供的getContentResolver()方法。

  ContentResolver cr = getContentResolver();

  ContentResolver提供的方法和ContentProvider提供的方法對應的有以下幾個方法。

  public Uri insert(Uri uri, ContentValues values) 用於添加數據到指定Uri的ContentProvider中。

  public int delete(Uri uri, String selection, String[] selectionArgs) 用於從指定Uri的ContentProvider中刪除數據。

  public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) 用於更新指定Uri的ContentProvider中的數據。

  public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 用於查詢指定Uri的ContentProvider。

  3.Uri

  Uri指定了將要操作的ContentProvider,其實可以把一個Uri看作是一個網址,我們把Uri分為三部分。

  第一部分是"content://"。可以看作是網址中的"http://"。

  第二部分是主機名或authority,用於唯一標識這個ContentProvider,外部應用需要根據這個標識來找到它。可以看作是網址中的主機名,比如"blog.csdn.net"。

  第三部分是路徑名,用來表示將要操作的數據。可以看作網址中細分的內容路徑。

 

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