首頁(yè)技術(shù)文章正文

Android+物聯(lián)網(wǎng)培訓(xùn)之四大組件和fragment

更新時(shí)間:2017-07-22 來(lái)源:黑馬程序員Android培訓(xùn)學(xué)院 瀏覽量:

Activity :
應(yīng)用程序中,一個(gè)Activity通常就是一個(gè)單獨(dú)的屏幕,它上面可以顯示一些控件也可以監(jiān)聽(tīng)并處理用戶的事件做出響應(yīng)。
Activity之間通過(guò)Intent進(jìn)行通信。Android培訓(xùn)學(xué)院認(rèn)為,在Intent的描述結(jié)構(gòu)中,有兩個(gè)最重要的部分:動(dòng)作和動(dòng)作對(duì)應(yīng)的數(shù)據(jù)。
典型的動(dòng)作類型有:M AIN(activity的門戶)、VIEW、PICK、EDIT 等。而動(dòng)作對(duì)應(yīng)的數(shù)據(jù)則以URI 的形式進(jìn)行表示。例如:要查看一個(gè)人的聯(lián)系方式,你需要?jiǎng)?chuàng)建一個(gè)動(dòng)作類型為VIEW 的intent,以及一個(gè)表示這個(gè)人的URI。
與之有關(guān)系的一個(gè)類叫IntentFilter。相對(duì)于intent 是一個(gè)有效的做某事的請(qǐng)求,一個(gè)intentfilter 則用于描述一個(gè)activity(或者IntentReceiver)能夠操作哪些intent。一個(gè)activity 如果要顯示一個(gè)人的聯(lián)系方式時(shí),需要聲明一個(gè)IntentFilter,這個(gè)IntentFilter 要知道怎么去處理VIEW 動(dòng)作和表示一個(gè)人的URI。IntentFilter需要在AndroidManifest.xml 中定義。通過(guò)解析各種intent,從一個(gè)屏幕導(dǎo)航到另一個(gè)屏幕是很簡(jiǎn)單的。當(dāng)向前導(dǎo)航時(shí),activity 將會(huì)調(diào)用startActivity(IntentmyIntent)方法。然后,系統(tǒng)會(huì)在所有安裝的應(yīng)用程序中定義的IntentFilter 中查找,找到最匹配myIntent 的Intent 對(duì)應(yīng)的activity。新的activity 接收到myIntent 的通知后,開始運(yùn)行。當(dāng)startActivity 方法被調(diào)用將觸發(fā)解析myIntent 的動(dòng)作,這個(gè)機(jī)制提供了兩個(gè)關(guān)鍵好處:
A、Activities 能夠重復(fù)利用從其它組件中以Intent 的形式產(chǎn)生的一個(gè)請(qǐng)求;Android培訓(xùn)學(xué)院
B、Activities 可以在任何時(shí)候被一個(gè)具有相同IntentFilter 的新的Activity 取代。
AndroidManifest文件中含有如下過(guò)濾器的Activity組件為默認(rèn)啟動(dòng)類當(dāng)程序啟動(dòng)時(shí)系統(tǒng)自動(dòng)調(diào)用它
<intent-filter>      
      <actionandroid:name="android.intent.action.MAIN" />
      <categoryandroid:name="android.intent.category.LAUNCHER" />
</intent-filter>
BroadcastReceive廣播接收器:
你的應(yīng)用可以使用它對(duì)外部事件進(jìn)行過(guò)濾只對(duì)感興趣的外部事件(如當(dāng)電話呼入時(shí),或者數(shù)據(jù)網(wǎng)絡(luò)可用時(shí))進(jìn)行接收并做出響應(yīng)。廣播接收器沒(méi)有用戶界面。然而,它們可以啟動(dòng)一個(gè)activity或serice 來(lái)響應(yīng)它們收到的信息,或者用NotificationManager 來(lái)通知用戶。通知可以用很多種方式來(lái)吸引用戶的注意力──閃動(dòng)背燈、震動(dòng)、播放聲音等。一般來(lái)說(shuō)是在狀態(tài)欄上放一個(gè)持久的圖標(biāo),用戶可以打開它并獲取消息。
廣播類型:
普通廣播,通過(guò)Context.sendBroadcast(IntentmyIntent)發(fā)送的
有序廣播通過(guò)Context.sendOrderedBroadcast(intent,receiverPermission)發(fā)送的,該方法第2個(gè)參數(shù)決定該廣播的級(jí)別,級(jí)別數(shù)值是在 -1000 到 1000 之間 , 值越大 , 發(fā)送的優(yōu)先級(jí)越高;廣播接收者接收廣播時(shí)的級(jí)別級(jí)別(可通過(guò)intentfilter中的priority進(jìn)行設(shè)置設(shè)為2147483647時(shí)優(yōu)先級(jí)最高),同級(jí)別接收的先后是隨機(jī)的, 再到級(jí)別低的收到廣播,高級(jí)別的或同級(jí)別先接收到廣播的可以通過(guò)abortBroadcast()方法截?cái)鄰V播使其他的接收者無(wú)法收到該廣播,還有其他構(gòu)造函數(shù)
異步廣播,通過(guò)Context.sendStickyBroadcast(IntentmyIntent)發(fā)送的,還有sendStickyOrderedBroadcast(intent,resultReceiver, scheduler,initialCode, initialData, initialExtras)方法,該方法具有有序廣播的特性也有異步廣播的特性;發(fā)送異步廣播要:<uses-permission android:name="android.permission.BROADCAST_STICKY"/>權(quán)限,接收并處理完Intent后,廣播依然存在,直到你調(diào)用removeStickyBroadcast(intent)主動(dòng)把它去掉
注意:發(fā)送廣播時(shí)的intent參數(shù)與Contex.startActivity()啟動(dòng)起來(lái)的Intent不同,前者可以被多個(gè)訂閱它的廣播接收器調(diào)用,后者只能被一個(gè)(Activity或service)調(diào)用
監(jiān)聽(tīng)廣播Intent步驟:
1> 寫一個(gè)繼承BroadCastReceiver的類,重寫onReceive()方法,廣播接收器僅在它執(zhí)行這個(gè)方法時(shí)處于活躍狀態(tài)。當(dāng)onReceive()返回后,它即為失活狀態(tài),注意:為了保證用戶交互過(guò)程的流暢,一些費(fèi)時(shí)的操作要放到線程里,如類名SMSBroadcastReceiver
2> 注冊(cè)該廣播接收者,注冊(cè)有兩種方法程序動(dòng)態(tài)注冊(cè)和AndroidManifest文件中進(jìn)行靜態(tài)注冊(cè)(可理解為系統(tǒng)中注冊(cè))如下:
靜態(tài)注冊(cè),注冊(cè)的廣播,下面的priority表示接收廣播的級(jí)別"2147483647"為最高優(yōu)先級(jí)
<receiverandroid:name=".SMSBroadcastReceiver" >
  <intent-filter android:priority="2147483647" >
    <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
  </intent-filter>
</receiver >
動(dòng)態(tài)注冊(cè),一般在Activity可交互時(shí)onResume()內(nèi)注冊(cè)BroadcastReceiver
IntentFilter intentFilter=newIntentFilter("android.provider.Telephony.SMS_RECEIVED");
registerReceiver(mBatteryInfoReceiver,intentFilter);

//反注冊(cè)
unregisterReceiver(receiver);
注意:
1.生命周期只有十秒左右,如果在 onReceive() 內(nèi)做超過(guò)十秒內(nèi)的事情,就會(huì)報(bào)ANR(ApplicationNo Response) 程序無(wú)響應(yīng)的錯(cuò)誤信息,如果需要完成一項(xiàng)比較耗時(shí)的工作 , 應(yīng)該通過(guò)發(fā)送 Intent 給Service, 由Service 來(lái)完成 . 這里不能使用子線程來(lái)解決 , 因?yàn)?BroadcastReceiver 的生命周期很短 , 子線程可能還沒(méi)有結(jié)束BroadcastReceiver就先結(jié)束了 .BroadcastReceiver一旦結(jié)束 , 此時(shí) BroadcastReceiver 的所在進(jìn)程很容易在系統(tǒng)需要內(nèi)存時(shí)被優(yōu)先殺死 , 因?yàn)樗鼘儆诳者M(jìn)程 ( 沒(méi)有任何活動(dòng)組件的進(jìn)程 ). 如果它的宿主進(jìn)程被殺死 , 那么正在工作的子線程也會(huì)被殺死 . 所以采用子線程來(lái)解決是不可靠的
2. 動(dòng)態(tài)注冊(cè)廣播接收器還有一個(gè)特點(diǎn),就是當(dāng)用來(lái)注冊(cè)的Activity關(guān)掉后,廣播也就失效了。靜態(tài)注冊(cè)無(wú)需擔(dān)憂廣播接收器是否被關(guān)閉,只要設(shè)備是開啟狀態(tài),廣播接收器也是打開著的。也就是說(shuō)哪怕app本身未啟動(dòng),該app訂閱的廣播在觸發(fā)時(shí)也會(huì)對(duì)它起作用
系統(tǒng)常見(jiàn)廣播Intent,如開機(jī)啟動(dòng)、電池電量變化、時(shí)間改變等廣播
Service 服務(wù):
一個(gè)Service 是一段長(zhǎng)生命周期的,沒(méi)有用戶界面的程序,可以用來(lái)開發(fā)如監(jiān)控類程序。
比較好的一個(gè)例子就是一個(gè)正在從播放列表中播放歌曲的媒體播放器。在一個(gè)媒體播放器的應(yīng)用中,應(yīng)該會(huì)有多個(gè)activity,讓使用者可以選擇歌曲并播放歌曲。然而,音樂(lè)重放這個(gè)功能并沒(méi)有對(duì)應(yīng)的activity,因?yàn)槭褂谜弋?dāng)然會(huì)認(rèn)為在導(dǎo)航到其它屏幕時(shí)音樂(lè)應(yīng)該還在播放的。在這個(gè)例子中,媒體播放器這個(gè)activity 會(huì)使用Context.startService()來(lái)啟動(dòng)一個(gè)service,從而可以在后臺(tái)保持音樂(lè)的播放。同時(shí),系統(tǒng)也將保持這個(gè)service 一直執(zhí)行,直到這個(gè)service 運(yùn)行結(jié)束。另外,我們還可以通過(guò)使用Context.bindService()方法,連接到一個(gè)service 上(如果這個(gè)service 還沒(méi)有運(yùn)行將啟動(dòng)它)。當(dāng)連接到一個(gè)service 之后,我們還可以service 提供的接口與它進(jìn)行通訊。拿媒體播放器這個(gè)例子來(lái)說(shuō),我們還可以進(jìn)行暫停、重播等操作。
Service使用步驟如下
1>繼承service類
2>AndroidManifast.xml配置清單文件中<application>節(jié)點(diǎn)里對(duì)服務(wù)進(jìn)行配置
<servicename=".SMSService"/>
服務(wù)不能自己運(yùn)行,需要通過(guò)Contex.startService()或Contex.bindService()啟動(dòng)服務(wù)
通過(guò)startService()方法啟動(dòng)的服務(wù)于調(diào)用者沒(méi)有關(guān)系,即使調(diào)用者關(guān)閉了,服務(wù)仍然運(yùn)行想停止服務(wù)要調(diào)用Context.stopService(),此時(shí)系統(tǒng)會(huì)調(diào)用onDestory(),使用此方法啟動(dòng)時(shí),服務(wù)首次啟動(dòng)系統(tǒng)先調(diào)用服務(wù)的onCreate()-->onStart(),如果服務(wù)已經(jīng)啟動(dòng)再次調(diào)用只會(huì)觸發(fā)onStart()方法
使用bindService()啟動(dòng)的服務(wù)與調(diào)用者綁定,只要調(diào)用者關(guān)閉服務(wù)就終止,使用此方法啟動(dòng)時(shí),服務(wù)首次啟動(dòng)系統(tǒng)先調(diào)用服務(wù)的onCreate()-->onBind(),如果服務(wù)已經(jīng)啟動(dòng)再次調(diào)用不會(huì)再觸發(fā)這2個(gè)方法,調(diào)用者退出時(shí)系統(tǒng)會(huì)調(diào)用服務(wù)的onUnbind()-->onDestory(),想主動(dòng)解除綁定可使用Contex.unbindService(),系統(tǒng)依次調(diào)用onUnbind()-->onDestory();
Content Provider內(nèi)容提供者 :
android平臺(tái)提供了Content Provider使一個(gè)應(yīng)用程序的指定數(shù)據(jù)集提供給其他應(yīng)用程序。這些數(shù)據(jù)可以存儲(chǔ)在文件系統(tǒng)中、在一個(gè)SQLite數(shù)據(jù)庫(kù)、或以任何其他合理的方式,
其他應(yīng)用可以通過(guò)ContentResolver類(見(jiàn)ContentProviderAccessApp例子)從該內(nèi)容提供者中獲取或存入數(shù)據(jù).(相當(dāng)于在應(yīng)用外包了一層殼),
只有需要在多個(gè)應(yīng)用程序間共享數(shù)據(jù)是才需要內(nèi)容提供者。例如,通訊錄數(shù)據(jù)被多個(gè)應(yīng)用程序使用,且必須存儲(chǔ)在一個(gè)內(nèi)容提供者中
它的好處:統(tǒng)一數(shù)據(jù)訪問(wèn)方式。
android系統(tǒng)自帶的內(nèi)容提供者(頂級(jí)的表示數(shù)據(jù)庫(kù)名,非頂級(jí)的都是表名)這些內(nèi)容提供者在SDK文檔的android.providerJava包中都有介紹。見(jiàn):http://developer.android.com/reference/android/provider/package-summary.html
├────Browser
├────CallLog
├────Contacts
│ ├────Groups
│ ├────People
│ ├────Phones
│ └────Photos
├────Images
│ └────Thumbnails
├────MediaStore
│ ├────Albums
│ ├────Artists
│ ├────Audio
│ ├────Genres
│ └────Playlists
├────Settings
└────Video
CallLog:地址和接收到的電話信息
Contact.People.Phones:存儲(chǔ)電話號(hào)碼
Setting.System:系統(tǒng)設(shè)置和偏好設(shè)置
使用Content Provider對(duì)外共享數(shù)據(jù)的步驟
1>繼承ContentProvider類并根據(jù)需求重寫以下方法:
    public boolean onCreate();//處理初始化操作

      /**
       * 插入數(shù)據(jù)到內(nèi)容提供者(允許其他應(yīng)用向你的應(yīng)用中插入數(shù)據(jù)時(shí)重寫)
       * @param uri
       * @paraminitialValues 插入的數(shù)據(jù)
       * @return
       */
      public Uriinsert(Uri uri, ContentValues initialValues);

      /**
       * 從內(nèi)容提供者中刪除數(shù)據(jù)(允許其他應(yīng)用刪除你應(yīng)用的數(shù)據(jù)時(shí)重寫)
       * @param uri
       * @paramselection 條件語(yǔ)句
       * @paramselectionArgs 參數(shù)
       * @return
       */
      public intdelete(Uri uri, String selection, String[] selectionArgs);

      /**
       * 更新內(nèi)容提供者已存在的數(shù)據(jù)(允許其他應(yīng)用更新你應(yīng)用的數(shù)據(jù)時(shí)重寫)
       * @param uri
       * @paramvalues 更新的數(shù)據(jù)
       * @paramselection 條件語(yǔ)句
       * @paramselectionArgs 參數(shù)
       * @return
       */
      public intupdate(Uri uri, ContentValues values, String selection,
                    String[]selectionArgs);

      /**
       * 返回?cái)?shù)據(jù)給調(diào)用者(允許其他應(yīng)用從你的應(yīng)用中獲取數(shù)據(jù)時(shí)重寫)
       * @param uri
       * @paramprojection 列名
       * @param selection條件語(yǔ)句
       * @paramselectionArgs 參數(shù)
       * @paramsortOrder 排序
       * @return
       */
      public Cursorquery(Uri uri, String[] projection, String selection,
                    String[]selectionArgs,String sortOrder) ;         

      /**
       * 用于返回當(dāng)前Uri所代表數(shù)據(jù)的MIME類型
       * 如果操作的數(shù)據(jù)為集合類型(多條數(shù)據(jù)),那么返回的類型字符串應(yīng)該為vnd.android.cursor.dir/開頭
       * 例如要得到所有person記錄的Uri為content://com.bravestarr.provider.personprovider/person,
     *   那么返回的MIME類型字符串應(yīng)該為"vnd.android.cursor.dir/person"
       * 如果操作的數(shù)據(jù)為單一數(shù)據(jù),那么返回的類型字符串應(yīng)該為vnd.android.cursor.item/開頭
       * 例如要得到id為10的person記錄的Uri為content://com.bravestarr.provider.personprovider/person/10,
     *   那么返回的MIME類型字符串應(yīng)該為"vnd.android.cursor.item/person"
       * @param uri
       */
      public String getType(Uriuri)
Android培訓(xùn)學(xué)院認(rèn)為這些方法中的Uri參數(shù),得到后需要進(jìn)行解析然后做對(duì)應(yīng)處理,Uri表示要操作的數(shù)據(jù),包含兩部分信息:
1.需要操作的contentprovider
2.對(duì)contentprovider中的什么數(shù)據(jù)進(jìn)行操作,一個(gè)Uri格式:結(jié)構(gòu)頭://authorities(域名)/路徑(要操作的數(shù)據(jù),根據(jù)業(yè)務(wù)而定)
content://com.bravestarr.provider.personprovider/person/10
說(shuō)明:contentprovider的結(jié)構(gòu)頭已經(jīng)由android規(guī)定為content://
authorities用于唯一標(biāo)識(shí)這個(gè)contentprovider程序,外部調(diào)用者可以根據(jù)這個(gè)找到他
路徑表示我們要操作的數(shù)據(jù),路徑的構(gòu)建根據(jù)業(yè)務(wù)而定.路徑格式如下:
要操作person表行號(hào)為10的記錄,可以這樣構(gòu)建/person/10
要操作person表的所有記錄,可以這樣構(gòu)建/person
2>在AndroidManifest.xml中使用<provider>對(duì)ContentProvider進(jìn)行配置注冊(cè)(內(nèi)容提供者注冊(cè)它自己就像網(wǎng)站注冊(cè)域名),ContentProvider采用authoritie(原意授權(quán),可理解為域名)作為唯一標(biāo)識(shí),方便其他應(yīng)用能找到
<application
      android:icon="@drawable/ic_launcher"
      android:label="@string/app_name" >
       <!--authorities屬性命名建議:公司名.provider.SomeProvider-->
       <providerandroid:name=".PersonProvider"android:authorities="com.bravestarr.provider.personprovider"/>
       ...
</application>


fragment這里直接上網(wǎng)頁(yè)鏈接了啊。
http://blog.csdn.net/lmj623565791/article/details/37970961


本文版權(quán)歸黑馬程序員Android+物聯(lián)網(wǎng)培訓(xùn)學(xué)院所有,歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明作者出處。謝謝!
作者:黑馬程序員Android+物聯(lián)網(wǎng)培訓(xùn)學(xué)院
首發(fā):http://Android.itheima.com
分享到:
在線咨詢 我要報(bào)名
和我們?cè)诰€交談!