任何技能的熟練都離不開扎實的基礎知識,時不時的回顧這些基礎內容會對開發(fā)技能的理解有很好的幫助。
隨著學習的進度隨時更新基礎知識
一、前言
本章內容甚多,參考了許多大能的文章,感謝各位大能的分享。
Android之Activity全面解析
Android Activity 你所需要知道的一切
務必知道的Android service的完全詳解
Android Service一些知識與理解
Android BroadcastReceiver詳解
Android四大組件:BroadcastReceiver史上最全面解析
Android四大組件——ContentProvider(基礎篇)
Android ContentProvider詳解
二、四大組件之Activity
1. Activity生命周期

完整生命周期
onCreate-->onStart-->onResume-->onPause-->onStop-->onDestory
可視生命周期
onStart-->onResume-->onPause-->onStop
前臺生命周期
onResume-->onPause
兩個Activity先后啟動時的調用方式
第一個Activity的啟動順序
onCreate() >> onStart() >> onResume()
第二個Activity啟動時
(OneActivity)onPause() >> (TwoActivity)onCreate() >> onStart() >> onResume() >> (OneActivity)onStop()
返回到第一個Activity時
(TwoActivity)onPause() >> (OneActivity)onRestart() >> onStart() >> onResume() >> (TwoActivity)onStop() >> onDestroy()
如果給第二個activity設置透明窗口主題(android:theme="@style/Base.Theme.AppCompat.Dialog")
從第一個activity跳轉到第二個activity過程:
AActivity: onCreate() >> onStart() >> onResume() >> onPause()(A依然可見但不可交互)
BActivity: onCreate() >> onStart() >> onResume()(B以窗口對話框形式在AActivity上面,可見可交互)
點擊空白處或者返回:
BActivity: onPause()
AActivity: onResume()
BActivity: onStop() >> onDestory()
Activity被銷毀時,數據保存問題
系統(tǒng)通過調用onSaveInstanceState()和onRestoreInstanceState()來保存和恢復數據。
- onSaveInstanceState():Activity被異常終止,在Activity即將被銷毀且有機會重新顯示的情況下,系統(tǒng)會自動調用;Android3.0之前在onPause()之前調用,Android3.0之后是在onPause()之后onStop()之前調用;系統(tǒng)會傳遞一個Bundle對象保存信息。
- onRestoreInstanceState():在Activity確定被銷毀以后,重建Activity時調用,在onStart()之后執(zhí)行;系統(tǒng)保存的Bundle對象會傳遞到onRestoreInstanceState()和onCreate()中,可以根據實際情況來選擇在那個方法中恢復數據。
- 屏幕進行橫豎屏切換時。(系統(tǒng)默認情況下) 在屏幕切換之前,系統(tǒng)會銷毀Activity A,在屏幕切換之后系統(tǒng)又會自動地創(chuàng)建Activity A,所以onSaveInstanceState一定會被執(zhí)行。
并且在默認情況下,切換橫豎屏會調用各個生命周期方法,橫屏調一次,豎屏調用2次;我們可以清單文件manifest file中聲明Activity時配置configChanges屬性來改變生命周期的調用次數:
(1)設置android:configChanges="orientation"
(2)設置android:configChanges="orientation|keyboardHidden"(3.2系統(tǒng)之前的系統(tǒng)不會執(zhí)行生命周期方法了)
(3)設置android:configChanges="orientation|keyboardHidden|screenSize"可以控制Activity在橫豎屏切換時不銷毀重建,只會執(zhí)行onConfigurationChanged方法。
2. Activity四種啟動模式
每個應用程序都有自己的Activity任務棧,用來存放所有啟動的Activity,任務棧使用先入后出的操作方式,并且每次啟動的Activity都會實例化并放入任務棧,會出現同一個Activity存在多個實例的情況,Android提供了四種啟動模式,我們可以根據實際情況選擇不同的啟動模式。
在清單文件manifest file中聲明Activity時,可以使用<activity> 元素的launchMode屬性指定Activity在啟動時應如何與任務關聯:
| Modes | Description |
|---|---|
| "standard" | 默認模式。系統(tǒng)在啟動它的任務中創(chuàng)建Activity的新實例,并將意圖路由到該實例。Activity可以多次實例化,每個實例可以屬于不同的任務,一個任務可以有多個實例。 |
| "singleTop" | 如果任務棧的棧頂存在這個要開啟的Activity,不會重新的創(chuàng)建Activity,而是復用已經存在的Activity。保證棧頂如果存在,不會重復創(chuàng)建。 |
| "singleTask" | 當開啟Activity的時候,就去檢查在任務棧里面是否有實例已經存在,如果有實例存在就復用這個已經存在的Activity,并且把這個Activity上面的所有的別的Activity都清空,復用這個已經存在的Activity。保證整個任務棧里面只有一個實例存在。 |
| "singleInstance" | 相同"singleTask",區(qū)別在于:系統(tǒng)不啟動任何其他Activity納入控制實例的任務。Activity始終是其任務的唯一成員; 任何由此開始的Activity都在一個單獨的任務中打開。 |
3. Activity的兩種啟動方式
顯示啟動
常用的啟動方式,在AndroidManifest.xml里配置activity,然后進行如下操作:
Intent intent = new Intent(MainActivity.this,CloneActivity.class);
startActivity(intent);
隱式啟動
它與顯示啟動最大區(qū)別就是不需要在Intent的實例化中傳參, 但是需要在AndroidManifest.xml給該activity配置intentfilter屬性,啟動代碼如下
<intent-filter>
<action android:name="com.mangoer.activityreview"></action>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
Intent intent = new Intent();
intent.setAction("com.mangoer.activityreview");
startActivity(intent);
二、四大組件之Service
1. Service介紹
Service是一種可以在后臺長期運行的組件,沒有UI界面;適合執(zhí)行不需要交互、不需要界面的任務;需要注意的是,Service默認是運行在Main線程中,如果在Service中進行耗時操作,也會造成程序無響應(ANR)的問題。
2. 啟動方式
Service有兩種啟動方式:
- start啟動:組件通過startService()啟動,啟動后,服務會在后臺一直運行,及時調用組件被銷毀也不會影響到服務的運行,服務也不會將執(zhí)行的結果返回給組件;當手動停止服務或者執(zhí)行的任務完成后服務會停止。
- bind啟動:組件通過bindService()啟動,組件和服務進行綁定,可以進行數據交互;一個服務可以綁定多個組件,只有每個組件都與服務進行解綁后,服務才會停止。
不管哪種啟動方式,都先要在清單(AndroidManifest.xml)中進行聲明
<service android:name=".myservice"
android:enabled="true"
android:exported="true"
android:icon="@drawable/background"
android:label="string"
android:process="string"
android:permission="string"/>
| 屬性 | 說明 |
|---|---|
| android:exported | 表示是否允許除了當前程序之外的其他程序訪問這個服務 |
| android:enabled | 表示是否能啟用這個服務 |
| android:permission | 權限聲明,組件在啟動這個服務的時候必須要有的權限 |
| android:process | 是否需要在單獨的進程中運行,當設置為android:process=”:remote”時,代表Service在單獨的進程中運行。注意“:”很重要,它的意思是指要在當前進程名稱前面附加上當前的包名,所以“remote”和”:remote”不是同一個意思,前者的進程名稱為:remote,而后者的進程名稱為:App-packageName:remote |
| android:isolatedProcess | 設置 true 意味著,服務會在一個特殊的進程下運行,這個進程與系統(tǒng)其他進程分開且沒有自己的權限。與其通信的唯一途徑是通過服務的API(bind and start) |
3. 生命周期

(1)啟動Service服務
單次:startService() —> onCreate() —> onStartCommand()
多次:startService() —> onCreate() —> onStartCommand() —> onStartCommand()
(2)停止Service服務
stopService() —> onDestroy()
(3)綁定Service服務
bindService() —> onCreate() —> onBind()
(4)解綁Service服務
unbindService() —> onUnbind() —> onDestroy()
(5)先啟動再綁定Service服務
startService() —> onCreate() —> onStartCommand() —> bindService() —> onBind()
(6)解綁后停止Service服務
unbindService() —> onUnbind() —> stopService() —> onDestroy()
(7)解綁后再綁定Service服務
unbindService() —> onUnbind(ture) —> bindService() —> onRebind()
- 兩種啟動方式中onCreate()都只調用一次,多次startService()時,onStartCommand()會多次調用,而多次bindService()時,onBind()方法只調用一次。
- 當同時使用startService()和bindService()時,需同時調用unbindService()和stopService()才能使服務停止,單獨調用其中一個,服務都不會停止運行。
三、四大組件之BroadcastReceiver
BroadcastReceiver廣播接收器,用來監(jiān)聽廣播的組件,Android內置了一套廣播通信機制,通過廣播可以在不同APP、不同組件、不同線程之間進行通信。
Android中的廣播機制采用了觀察者模式,需要有廣播發(fā)送者和廣播接收者參與其中
1. 如何使用BroadcastReceiver
1.1、創(chuàng)建BroadcastReceiver
// 繼承BroadcastReceivre基類
public class mBroadcastReceiver extends BroadcastReceiver {
// 復寫onReceive()方法
// 接收到廣播后,則自動調用該方法
@Override
public void onReceive(Context context, Intent intent) {
//寫入接收廣播后的操作
}
}
1.2、注冊BroadcastReceiver
- 靜態(tài)注冊:直接在AndroidManifest.xml清單文件中通過標簽來注冊廣播,此方式注冊的廣播不受任何組件的生命周期影響,及時在程序關閉后,仍然可以接受廣播。
<receiver
android:enabled=["true" | "false"]
//此broadcastReceiver能否接收其他App的發(fā)出的廣播
//默認值是由receiver中有無intent-filter決定的:如果有intent-filter,默認值為true,否則為false
android:exported=["true" | "false"]
android:icon="drawable resource"
android:label="string resource"
//繼承BroadcastReceiver子類的類名
android:name=".mBroadcastReceiver"
//具有相應權限的廣播發(fā)送者發(fā)送的廣播才能被此BroadcastReceiver所接收;
android:permission="string"
//BroadcastReceiver運行所處的進程
//默認為app的進程,可以指定獨立的進程
//注:Android四大基本組件都可以通過此屬性指定自己的獨立進程
android:process="string" >
//用于指定此廣播接收器將接收的廣播類型
//本示例中給出的是用于接收網絡狀態(tài)改變時發(fā)出的廣播
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
- 動態(tài)注冊:在代碼注冊廣播,注冊后必須注銷,否則容易出現內存泄露
// 1. 實例化BroadcastReceiver子類 & IntentFilter
mBroadcastReceiver mBroadcastReceiver = new mBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
// 2. 設置接收廣播的類型
intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);
// 3. 動態(tài)注冊:調用Context的registerReceiver()方法
registerReceiver(mBroadcastReceiver, intentFilter);
// 注冊廣播后,要在相應位置記得銷毀廣播
// 即在onPause() 中unregisterReceiver(mBroadcastReceiver)
// 當此Activity實例化時,會動態(tài)將MyBroadcastReceiver注冊到系統(tǒng)中
// 當此Activity銷毀時,動態(tài)注冊的MyBroadcastReceiver將不再接收到相應的廣播。
@Override
protected void onPause() {
super.onPause();
//銷毀在onResume()方法中的廣播
unregisterReceiver(mBroadcastReceiver);
}
2. 廣播的分類
2.1、普通廣播(Normal Broadcast)
是一種無序廣播,所有跟廣播匹配的接收器都能接收到該廣播,并且沒有先后順序,廣播效率高,但是廣播接收器無法停止該廣播,無法將內容傳遞到其他接收器
2.2、有序廣播(Ordered Broadcast)
是一種同步廣播,根據廣播接收器屬性intent-filter中的android:priority屬性來設置優(yōu)先級,從-1000~1000數值越大優(yōu)先級越高,廣播根據優(yōu)先級依次傳遞廣播,每個廣播接收器都可以終止廣播,并且可以傳遞內容到下一個接收器
2.3、粘性廣播(Sticky Broadcast)
該廣播發(fā)送后會一直滯留在消息容器中,直到有匹配的廣播接收器接受該廣播,在Android5.0/API 21之后失效,不推薦使用
2.4、系統(tǒng)廣播(System Broadcast)
Android系統(tǒng)內置的廣播,涉及到手機的基本操作都會自動發(fā)出對應的廣播,每個廣播都有特定的action
| 系統(tǒng)操作 | action |
|---|---|
| 監(jiān)聽網絡變化 | android.net.conn.CONNECTIVITY_CHANGE |
| 關閉或打開飛行模式 | Intent.ACTION_AIRPLANE_MODE_CHANGED |
| 充電時或電量發(fā)生變化 | Intent.ACTION_BATTERY_CHANGED |
| 電池電量低 | Intent.ACTION_BATTERY_LOW |
| 電池電量充足(即從電量低變化到飽滿時會發(fā)出廣播 | Intent.ACTION_BATTERY_OKAY |
| 系統(tǒng)啟動完成后(僅廣播一次) | Intent.ACTION_BOOT_COMPLETED |
| 按下照相時的拍照按鍵(硬件按鍵)時 | Intent.ACTION_CAMERA_BUTTON |
| 屏幕鎖屏 | Intent.ACTION_CLOSE_SYSTEM_DIALOGS |
| 設備當前設置被改變時(界面語言、設備方向等) | Intent.ACTION_CONFIGURATION_CHANGED |
| 插入耳機時 | Intent.ACTION_HEADSET_PLUG |
| 未正確移除SD卡但已取出來時(正確移除方法:設置--SD卡和設備內存--卸載SD卡) | Intent.ACTION_MEDIA_BAD_REMOVAL |
| 插入外部儲存裝置(如SD卡) | Intent.ACTION_MEDIA_CHECKING |
| 成功安裝APK | Intent.ACTION_PACKAGE_ADDED |
| 成功刪除APK | Intent.ACTION_PACKAGE_REMOVED |
| 重啟設備 | Intent.ACTION_REBOOT |
| 屏幕被關閉 | Intent.ACTION_SCREEN_OFF |
| 屏幕被打開 | Intent.ACTION_SCREEN_ON |
| 關閉系統(tǒng)時 | Intent.ACTION_SHUTDOWN |
| 重啟設備 | Intent.ACTION_REBOOT |
2.5、本地廣播(Local Broadcast)
以上四類廣播都是全局廣播,只要有匹配的接收器,都可以接收到廣播,對性能及安全性都有一定的影響,于是有了本地廣播,此廣播只可通過代碼動態(tài)注冊,并且只有同一個APP內的廣播接收器接收的到
四、四大組件之ContentProvider
ContentProvider為不同的應用之間實現數據共享,提供統(tǒng)一的接口,可以實現進程間的數據共享,實現跨進程通信,ContentProvider其底層使用了Binder來完成APP進程之間的通信,同時使用匿名共享內存來作為共享數據的載體。ContentProvider支持訪問權限管理機制,以控制數據的訪問者及訪問方式,保證數據訪問的安全性。
1. 三大類
- ContentProvider(內容提供者)
- ContentResolver(內容解析者)
- ContentObserver(內容觀察者)
假如我們現在有個應用A 提供了數據 ,應用B要操作應用A的數據,那么
應用A使用ContentProvider(內容提供者)去共享自己數據
應用B使用ContentResolver(內容解析者)去操作應用A的數據
應用B通過ContentObserver(內容觀察者)去監(jiān)聽應用A的數據變化
當應用A的數據發(fā)送改變時,通知ContentObserver去告訴應用B數據變化了及時更新
2. URI
URI(Uniform Resource Identifier)即統(tǒng)一資源標識符,是一個用于標識某一互聯網資源名稱的字符串。以聯系人Contacts的Uri為例,其結構如下所示:

- schema: Android中固定為content://。
- authority: 用于唯一標識一個ContentProvider。
- path: ContentProvider中數據表的表名。
- id: 數據表中數據的標識,可選字段。
3. UriMatcher類
在ContentProvider 中注冊URI,根據 URI 匹配 ContentProvider 中對應的數據表,只提供了兩個方法——addURI和match方法。
4. ContentUris類
操作 URI,核心方法有兩個:withAppendedId()&parseId()
// withAppendedId()作用:向URI追加一個id
Uri uri = Uri.parse("content://cn.scu.myprovider/user")
Uri resultUri = ContentUris.withAppendedId(uri, 7);
// 最終生成后的Uri為:content://cn.scu.myprovider/user/7
// parseId()作用:從URL中獲取ID
Uri uri = Uri.parse("content://cn.scu.myprovider/user/7")
long personid = ContentUris.parseId(uri);
//獲取的結果為:7
5. ContentProvider的使用
ContentProvider 的使用可以簡單的歸納為以下幾步:
1、創(chuàng)建自己的數據列表;
2、自定義ContentProvider實現相關的抽象方法;
3、在AndroidManifest中聲明provider以及定義相關訪問權限;
4 、通過ContentResolver根據URI進行增刪改查。