Android基礎匯總之四大組件

任何技能的熟練都離不開扎實的基礎知識,時不時的回顧這些基礎內容會對開發(fā)技能的理解有很好的幫助。
隨著學習的進度隨時更新基礎知識

一、前言

本章內容甚多,參考了許多大能的文章,感謝各位大能的分享。
Android之Activity全面解析
Android Activity 你所需要知道的一切
務必知道的Android service的完全詳解
Android Service一些知識與理解
Android BroadcastReceiver詳解
Android四大組件:BroadcastReceiver史上最全面解析
Android四大組件——ContentProvider(基礎篇)
Android ContentProvider詳解

二、四大組件之Activity

1. Activity生命周期
image.png

完整生命周期
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. 生命周期
image.png

(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支持訪問權限管理機制,以控制數據的訪問者及訪問方式,保證數據訪問的安全性。
image.png
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為例,其結構如下所示:

image

  • 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進行增刪改查。

?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容