Android基礎四大元件詳解
Android四大元件詳解
博主接觸Android開發將近一年,從最初的JavaSE開始,到Android基礎,一直學的糊糊塗塗,最近想整理一番
android基礎, 順便把自己的學習開發經驗分享給大家(小白一個),大家覺得有什麼建議可以評論。
四大元件 Activity,Service,BroadCastReceiver,ContentProvider,是android中基礎的基礎,
所有android開發都離不開這四大基礎元件。
1.Activity
從Activity說起,activity從字面上的意思理解是活動行動的意思, 在Android中,
activity指與使用者互動的介面,從你開啟一個android應用所見到的第一個頁面,就是一個Activity
Activity作為一個可見的介面,給使用者以良好的體驗很重要,所以佈局的漂亮與否決定一個應用使用者體驗
及開發人員 的技術水平,佈局肯定是要掌握的咯(今天不講佈局).我們開發常見的有
FragmentActivitiyListActivity ,PreferenceActivity ,TabAcitivty等…
先從Activity的生命週期講起,一個activity的生命週期就像我們一樣,從出生到童年,青年,中年,老年
最後入土.Activity從建立到銷燬有多種狀態,從一種狀態到另一種狀態時會激發相應的回撥方法,從onCreate(),
onStart(),onPause(),onResume(),onstop(),onDestroy(),到onRestart()等方法.(最常使用)。
首先我們來說說onCreat()方法,谷歌官方的解釋是:當這個介面第一次建立的時候執行這個方法,當然
一般情況下,在一個應用中這個方法只會執行一次,(橫豎屏切換),既然這個方法最先執行,那我們就可以在
這個方法體裡面做一些初始化的操作,如 初始化view(setCountentView(view)),尋找控制元件 findViewById(id),
初始化一些資料等等。
執行完oncreate方法介面展示後,即當Activity變成可見的時候,開始執行onStart()方法 ,這個方法和
onStop()方法對應。這個方法的用處不怎麼大。
onResume()方法,當一個介面可以和使用者互動,獲取到焦點的的時候,執行這個方法,什麼是和使用者互動?
比如說,你點選螢幕上的按鈕,圖片等等,activity會給出不同的反應。
onPause()方法和onResume()方法對應,即activity不能和使用者互動的,activity失去焦點,介面上的view
不能被點選的時候執行。
onStop()方法,當activity不可見的時候,執行這個方法,如從一個activity跳轉到另一個activity時,跳轉
前的activity被跳轉後的activity遮擋,就會執行onStop()這個方法
onRestart()方法,從第一個activity跳轉到第二個activity,再返回第一個 activity時,就會執行這個方法
介面重新變得可見就會執行這個方法。
onDestroy()方法,當一個activity銷燬的時候呼叫這個方法,與onCreate()對應。
簡單來說,這些方法都是兩兩對應的,onCreate建立與onDestroy銷燬;onStart可見與onStop不可見;
onResume可編輯(即獲得焦點)與onPause(失去焦點)。
橫豎屏切換生命週期比較特殊,不同activity跳轉,而是銷燬當前activity並重新建立 在Androidmainfest清單檔案中宣告android:screenOrientation="portrait"屬性可以限制不可橫豎屏切換。 下面是一個Demo,
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.out.println("onCreate--------------------");
}
//點選按鈕實現頁面跳轉 TestActivity
public void click(View v) {
Intent intent = new Intent(this,TestActivity.class);
startActivity(intent);
}
//當Activity銷燬的時候執行
@Override
protected void onDestroy() {
System.out.println("onDestroy--------------------");
super.onDestroy();
}
//當頁面可見的時候呼叫
@Override
protected void onStart() {
System.out.println("onStart--------------------");
super.onStart();
}
//當Activity 不可見執行
@Override
protected void onStop() {
System.out.println("onStop--------------------");
super.onStop();
}
//當Activity正在進行互動 按鈕可以被點選了
@Override
protected void onResume() {
System.out.println("onResume--------------------");
super.onResume();
}
//當acctivity不再進行互動 按鈕不可以被點選
@Override
protected void onPause() {
System.out.println("onPause--------------------");
super.onPause();
}
//當介面重新載入
@Override
protected void onRestart() {
System.out.println("onRestart--------------------");
super.onRestart();
}
}
上面是很簡單的內容,接下來我們來扯一扯Activity的四種啟動模式
[1]標準 standard,大部分應用都是這個標準啟動模式。 [2]singleTop 單一頂部模式 當我們把Activity配置成 singleTop啟動模式的時候 ,當我們在開啟這個Activity的時候 就會檢查當前任務棧的棧頂是否有這個例項存在, 如果存在就不會建立新的例項,而是直接複用這個例項 ,應用場景:singleTop :瀏覽器書籤頁面 [3]singleTask 當我們 把Activity設定成singleTask啟動模式 會檢查當前任務棧 是否有例項開啟 ,如果有例項開啟,就會直接複用這個例項 , 並且會把這個例項上面其他的Activity 也清空,當前任務棧只有一個例項存在 應用場景:singeTask : 瀏覽器瀏覽的頁面 節約記憶體 [4]singleinstance :如果把一個Activity配置這種啟動模式,系統會為這個Activity單獨建立一個任務棧,這個Activity在自己的任務棧裡面存在 應用場景 singleInstance :來電頁面 做銷售 四種啟動模式都需要在清單檔案下的Activity節點下配置,如果不配置,則預設標準standard開啟activity
<activity
android:name=".SecondActivity"
android:launchMode="singleInstance"
>
</activity>
Activity暫且告一段落.
2.Service
Android下的服務是在後臺執行 也是沒有介面 可以理解成是沒有介面的Activity,Android系統會為每個
應用程式建立一個程序和執行緒(主執行緒),而開啟一個服務就會建立一個程序,可以在後臺看到。
我們來分析一下程序:
程序按優先順序分5中:
1.Foreground process 前臺程序,正在和使用者互動 相當於Activity執行了onResume方法這個程序最不容易被系統殺死。
2.Visible Process 視覺化程序,使用者可以看得見,但使用者不能進行互動,相當於Activity執行了onPause()方法。
3.Service Process 服務程序 , 當程序裡面通過startService開啟一個服務,這時候就屬於服務程序。
4. Background Process 後臺程序, 相當於Activity執行了onStop()方法。
5. Empty Process 空程序 空程序不會維持任何執行的元件,空程序最容易被殺死,有時候它沒有被立刻殺死的目的是為下一次開啟應用程式時提供開啟的速度。
在系統執行記憶體不足的情況下,會檢查正在正在執行的程序,殺死優先順序低的程序來騰出記憶體。
我們開啟服務有兩種方式: StartService() 和 BindService().
starService 開啟一個服務,會執行onCreate()方法,和onStart()方法,如果服務已經開啟,只會執行onStart()方法。
服務開啟後,就會在後臺長期執行,可以在設定介面找到,我們可以在設定介面手動關閉它,服務就會停止執行。
startService開啟服務也叫做非繫結模式開啟服務 ,生命週期 第一次執行的方法有 onCreate().onstartCommand(),到service關閉的時候執行onDestroy()方法。
bindService開啟服務也叫做繫結模式開啟服務,生命週期 第一次執行的方法有 onCreate(), onBind()方法,
銷燬的時候執行onUnBind(),onDestroy()方法, bindService開啟服務有個特點,它在設定介面時找不到的,所以我們無法手動在設定介面銷燬它,
不過它的生命週期依附於Activity,當Activity銷燬的時候,這個服務也就跟著銷燬。
上面兩種生命週期實在相對單純的模式下的情形,我們在開發的過程中還必須注意Service例項只會有一個,也就是說如果當前要啟動的Service已經存在了那麼就不會再次建立該Service當然也不會呼叫onCreate()方法;
一個Service可以被多個客戶進行繫結,只有所有繫結物件都執行了onBind()方法後該Service才會銷燬,不過如果有一個使用者執行了onStart()方法,那麼這個時候如果其他所有的bind客戶都執行了unBind()。
該Service也不會銷燬,很多應用都是用startService和bindService混合開啟服務,比如音樂播放器,第三方支付等
這時我們可能會有一個疑問:既然有StartService開啟服務,為什麼還要用bindService開啟服務?
目的就是為了使用bindserivce呼叫服務裡面的方法
這時就出現瞭解決程序間的通訊問題:IPC,
而使用IPC就需要使用 aidl.
aidl :Android inteface defation language Android介面定義語言
使用aidl語言的步驟 [1] 有一個服務 服務裡面有一個方法 這個方法在另外一個應用裡面呼叫 [2]在服務的內部定義一箇中間人物件(IBinder的例項)[3]在onbind方法裡面把我們定義的中間人物件返回 [4]把你想暴露的方法都定義在接口裡
[5]把定義的介面Iservice.java 檔案變成aidl檔案 注意aidl語言不認識public [6]系統會自動生產一個Iservice.java檔案 生產一個類 stub 系統會報錯. 把我們定義的中間人物件直接繼承Stub [7]想保證2個應用程式使用的是同一個aidl檔案 谷歌要求aidl檔案所生成的包名要相同 [8]獲取中間人物件方式不一樣 是通過stub類中的一個靜態方法獲取我們定義中間人物件 [9]通過獲取到的中間人物件,呼叫服務裡面的方法,實現IPC通訊。
兩種開啟服務的小Demo:
public class MainActivity extends Activity {
private MyConn conn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// 點選按鈕開啟服務
public void click1(View v) {
Intent intent = new Intent(this, FirstService.class);
startService(intent);
}
// 點選按鈕關閉服務
public void click2(View v) {
Intent intent = new Intent(this, FirstService.class);
stopService(intent);
}
//點選按鈕 通過bindservice 去連線服務
public void click3(View v) {
Intent intent = new Intent(this, FirstService.class);
conn = new MyConn();
bindService(intent, conn, BIND_AUTO_CREATE);
}
//點選按鈕 停在服務
public void click4(View v) {
Intent intent = new Intent(this, FirstService.class);
stopService(intent);
}
//當Activity銷燬的時候
@Override
protected void onDestroy() {
//取消繫結服務
unbindService(conn);
super.onDestroy();
}
//監聽服務的狀態
private class MyConn implements ServiceConnection{
//當服務連線成功的時候呼叫
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
//失去連線的時候呼叫
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
}
</pre><pre name="code" class="java">
public class FirstService extends Service {
//當通過bindservice 連線成功的時候執行
@Override
public IBinder onBind(Intent intent) {
System.out.println("onBind");
return null;
}
//當service第一次建立的時候呼叫
@Override
public void onCreate() {
System.out.println("onCreate");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
System.out.println("onDestroy");
super.onDestroy();
}
}
3.BroadCastReceiver
BroadCastReceiver是Android四大元件之一,主要用於接收系統或者app傳送的廣播事件
廣播分兩種: 有序廣播和無序廣播
內部通訊實現機制:通過Android系統的Binder機制實現通訊的
無序廣播:sendBroadcast()方法傳送的廣播為無序廣播,無序廣播邏輯上可以被任何廣播接受者接收到,優點是效率高。缺點是一個接收者不能將處理結果傳遞給下一個接收者,傳遞的資料在傳輸過程中不能被修改,並無法終止廣播的傳播。
有序廣播:sendOrderedBroadcast()方法傳送的廣播為有序廣播,有序廣播依次傳播,列如有三個廣播接收者A,B,C, 優先順序是A>B>C,
此時傳送一條廣播,那這個訊息先傳給A,再傳給B, 最後傳給C,每個接收者都有權終止廣播,比如B終止廣播,C就無法接受到,
此外A接收到廣播後可以對結果物件進行操作,當廣播傳給B時,B可以從結果物件中獲取A存入的資料。
在通過context.sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler,initialCode, initialData, initialExtras);時我們可以指定resultReceiver廣播接收者,
這個接收者我們可以認為是最終接收者,通常情況下如果比他優先順序更高的接收者如果沒有終止廣播,那麼他的onReceive方法會被執行兩次,
第一次是正常的按照優先順序順序執行,第二次是作為最終接收者接收,如果比他優先順序高的接收者終止了廣播,那麼他依然能接收到廣播。
在我們的專案中經常使用廣播接收者接收系統通知,比如開機啟動,sd卡掛載,低電量,外撥電話,鎖屏等等,
如果我們做的是播放器,那麼監聽到使用者鎖屏後我們應該將我們的播放器暫停等。
BroadcastReceiver有兩種註冊方法,在Androidmainfest中註冊廣播接收者稱為靜態註冊,在程式碼中註冊稱為動態註冊。
靜態註冊的廣播接收者只要app在系統中註冊則可以一直接收到廣播訊息,動態註冊的廣播接收者當註冊的activity或Service銷燬了那麼久接收不到廣播了,
所以一般應用都是靜態註冊的,有一些操作特別頻繁的廣播事件在Androidmainfest中註冊無效的,
如手機鎖屏廣播,在程式碼中我們可以用registerReceiver()方法去註冊廣播。
需要注意的地方:
1.BroadcastReceiver的生命週期是非常短暫的,在接收廣播的時候建立,onReceiver()方法結束之後銷燬
2. 廣播接收者中不要做一些耗時的工作,否則會彈出Application No Response(應用無響應anr)錯誤對話方塊,,一般耗時的較長的操作最好放在服務中完成。
3.最好也不要在廣播接收者中建立子執行緒做耗時操作,因為廣播接收者被銷燬後進程就成為空程序,而空程序很容易被系統殺掉。
Android中引入廣播機制的用意 :
1.程式間互通訊息(例如在自己的應用程式內監聽系統的來電)
2.效率上(參考UDP的廣播協議在區域網的方便性)
3.設計模式上(反轉控制的一種應用,類似監聽者模式)
傳送和接收廣播的小Demo;public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//點選按鈕傳送一條無序 廣播
public void click(View v) {
Intent intent = new Intent();
//設定傳送廣播的事件
intent.setAction("com.itcast.customreceiver");
intent.putExtra("name", "每天晚上7點準時開整~~");
//傳送廣播
sendBroadcast(intent);
}
}
</pre></div><div><pre name="code" class="java"><pre name="code" class="java">public class ReceiveCusomReceiver extends BroadcastReceiver {
//這個方法接收我們自定義傳送的廣播
@Override
public void onReceive(Context context, Intent intent) {
//終止廣播
abortBroadcast();
String name = intent.getStringExtra("name");
Toast.makeText(context, name, 0).show();
}
}
4.ContentProvider
最後我們來介紹一下內容提供者ContentProvider
在Android中如果想將自己應用的資料(多為資料庫中的資料)提供給第三方應用,那麼我們只能通過ContentProvider來實現了。
ContentProvider是應用程式之間共享資料的介面,使用的時候首先自定義一個類繼承ContentProvider,然後重寫query,insert,updata,delete等方法。
因為內容提供者是四大元件之一,因此必須在AndroidMainfest檔案中進行註冊。
程式碼如下:
public class OtherActivity extends ContentProvider {
@Override
public boolean onCreate() {
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
return null;
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
return 0;
}
}
AndroidMainfest中註冊:
<provider android:name="com.example.mangjiang.otherprovider"
android:exported="true"></provider>
第三方可以通過內容解析者ContentResolver來訪問該Provider,另外還有內容觀察者ContentObserver,
這裡不一一贅述。
Android為什麼要有Activity,Service,BroadCastReceiver,ContentProvider?
因為現在的移動開發模式基本上也是照搬web那一套MVC框架,只不過改了點嫁妝而已,四大元件本質上就是為了實現移動或者說是嵌入式裝置上的MVC架構,
它們之間有時候是一種相互依存的關係,有時候又是一種補充關係。
這篇部落格很多地方是理論知識,或許會覺得很枯燥,耐心閱讀,掌握這些基礎知識,對以後的android開發會有很大的幫助!
有什麼不足的地方請各位大牛指點!