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

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

更新時間:2017-07-22 來源:黑馬程序員Android培訓學院 瀏覽量:

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

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

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

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

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

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

      /**
       * 用于返回當前Uri所代表數(shù)據(jù)的MIME類型
       * 如果操作的數(shù)據(jù)為集合類型(多條數(shù)據(jù)),那么返回的類型字符串應該為vnd.android.cursor.dir/開頭
       * 例如要得到所有person記錄的Uri為content://com.bravestarr.provider.personprovider/person,
     *   那么返回的MIME類型字符串應該為"vnd.android.cursor.dir/person"
       * 如果操作的數(shù)據(jù)為單一數(shù)據(jù),那么返回的類型字符串應該為vnd.android.cursor.item/開頭
       * 例如要得到id為10的person記錄的Uri為content://com.bravestarr.provider.personprovider/person/10,
     *   那么返回的MIME類型字符串應該為"vnd.android.cursor.item/person"
       * @param uri
       */
      public String getType(Uriuri)
Android培訓學院認為這些方法中的Uri參數(shù),得到后需要進行解析然后做對應處理,Uri表示要操作的數(shù)據(jù),包含兩部分信息:
1.需要操作的contentprovider
2.對contentprovider中的什么數(shù)據(jù)進行操作,一個Uri格式:結(jié)構(gòu)頭://authorities(域名)/路徑(要操作的數(shù)據(jù),根據(jù)業(yè)務而定)
content://com.bravestarr.provider.personprovider/person/10
說明:contentprovider的結(jié)構(gòu)頭已經(jīng)由android規(guī)定為content://
authorities用于唯一標識這個contentprovider程序,外部調(diào)用者可以根據(jù)這個找到他
路徑表示我們要操作的數(shù)據(jù),路徑的構(gòu)建根據(jù)業(yè)務而定.路徑格式如下:
要操作person表行號為10的記錄,可以這樣構(gòu)建/person/10
要操作person表的所有記錄,可以這樣構(gòu)建/person
2>在AndroidManifest.xml中使用<provider>對ContentProvider進行配置注冊(內(nèi)容提供者注冊它自己就像網(wǎng)站注冊域名),ContentProvider采用authoritie(原意授權(quán),可理解為域名)作為唯一標識,方便其他應用能找到
<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)頁鏈接了啊。
http://blog.csdn.net/lmj623565791/article/details/37970961


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