安卓四大组件
Android四大組件分別為activity、service、contentprovider、broadcast receiver。
一、android四大組件詳解
1、activity
(1)一個Activity通常就是一個單獨的屏幕(窗口)。
(2)Activity之間通過Intent進行通信。
(3)android應用中每一個Activity都必須要在AndroidManifest.xml配置文件中聲明,否則系統將不識別也不執行該Activity。
2、service
(1)service用于在后臺完成用戶指定的操作。service分為兩種:
(a)started(啟動):當應用程序組件(如activity)調用startService()方法啟動服務時,服務處于started狀態。
(b)bound(綁定):當應用程序組件調用bindService()方法綁定到服務時,服務處于bound狀態。
(2)startService()與bindService()區別:
(a)started service(啟動服務)是由其他組件調用startService()方法啟動的,這導致服務的onStartCommand()方法被調用。當服務是started狀態時,其生命周期與啟動它的組件無關,并且可以在后臺無限期運行,即使啟動服務的組件已經被銷毀。因此,服務需要在完成任務后調用stopSelf()方法停止,或者由其他組件調用stopService()方法停止。
(b)使用bindService()方法啟用服務,調用者與服務綁定在了一起,調用者一旦退出,服務也就終止,大有“不求同時生,必須同時死”的特點。
(3)開發人員需要在應用程序配置文件中聲明全部的service,使用<service></service>標簽。
(4)Service通常位于后臺運行,它一般不需要與用戶交互,因此Service組件沒有圖形用戶界面。Service組件需要繼承Service基類。Service組件通常用于為其他組件提供后臺服務或監控其他組件的運行狀態。
3、content provider
(1)android平臺提供了ContentProvider使一個應用程序的指定數據集提供給其他應用程序。其他應用可以通過ContentResolver類從該內容提供者中獲取或存入數據。
(2)只有需要在多個應用程序間共享數據是才需要內容提供者。例如,通訊錄數據被多個應用程序使用,且必須存儲在一個內容提供者中。它的好處是統一數據訪問方式。
(3)ContentProvider實現數據共享。ContentProvider用于保存和獲取數據,并使其對所有應用程序可見。這是不同應用程序間共享數據的唯一方式,因為android沒有提供所有應用共同訪問的公共存儲區。
(4)開發人員不會直接使用ContentProvider類的對象,大多數是通過ContentResolver對象實現對ContentProvider的操作。
(5)ContentProvider使用URI來唯一標識其數據集,這里的URI以content://作為前綴,表示該數據由ContentProvider來管理。
4、broadcast receiver
(1)你的應用可以使用它對外部事件進行過濾,只對感興趣的外部事件(如當電話呼入時,或者數據網絡可用時)進行接收并做出響應。廣播接收器沒有用戶界面。然而,它們可以啟動一個activity或serice來響應它們收到的信息,或者用NotificationManager來通知用戶。通知可以用很多種方式來吸引用戶的注意力,例如閃動背燈、震動、播放聲音等。一般來說是在狀態欄上放一個持久的圖標,用戶可以打開它并獲取消息。
(2)廣播接收者的注冊有兩種方法,分別是程序動態注冊和AndroidManifest文件中進行靜態注冊。
(3)動態注冊廣播接收器特點是當用來注冊的Activity關掉后,廣播也就失效了。靜態注冊無需擔憂廣播接收器是否被關閉,只要設備是開啟狀態,廣播接收器也是打開著的。也就是說哪怕app本身未啟動,該app訂閱的廣播在觸發時也會對它起作用。
二、android四大組件總結:
(1)4大組件的注冊
4大基本組件都需要注冊才能使用,每個Activity、service、Content Provider都需要在AndroidManifest文件中進行配置。AndroidManifest文件中未進行聲明的activity、服務以及內容提供者將不為系統所見,從而也就不可用。而broadcast receiver廣播接收者的注冊分靜態注冊(在AndroidManifest文件中進行配置)和通過代碼動態創建并以調用Context.registerReceiver()的方式注冊至系統。需要注意的是在AndroidManifest文件中進行配置的廣播接收者會隨系統的啟動而一直處于活躍狀態,只要接收到感興趣的廣播就會觸發(即使程序未運行)。
(2)4大組件的激活
內容提供者的激活:當接收到ContentResolver發出的請求后,內容提供者被激活。而其它三種組件activity、服務和廣播接收器被一種叫做intent的異步消息所激活。
(3)4大組件的關閉
內容提供者僅在響應ContentResolver提出請求的時候激活。而一個廣播接收器僅在響應廣播信息的時候激活。所以,沒有必要去顯式的關閉這些組件。Activity關閉:可以通過調用它的finish()方法來關閉一個activity。服務關閉:對于通過startService()方法啟動的服務要調用Context.stopService()方法關閉服務,使用bindService()方法啟動的服務要調用Contex.unbindService()方法關閉服務。
(4)android中的任務(activity棧)
(a)任務其實就是activity的棧,它由一個或多個Activity組成,共同完成一個完整的用戶體驗。棧底的是啟動整個任務的Activity,棧頂的是當前運行的用戶可以交互的Activity,當一個activity啟動另外一個的時候,新的activity就被壓入棧,并成為當前運行的activity。而前一個activity仍保持在棧之中。當用戶按下BACK鍵的時候,當前activity出棧,而前一個恢復為當前運行的activity。棧中保存的其實是對象,棧中的Activity永遠不會重排,只會壓入或彈出。
(b)任務中的所有activity是作為一個整體進行移動的。整個的任務(即activity棧)可以移到前臺,或退至后臺。
(c)Android系統是一個多任務(Multi-Task)的操作系統,可以在用手機聽音樂的同時,也執行其他多個程序。每多執行一個應用程序,就會多耗費一些系統內存,當同時執行的程序過多,或是關閉的程序沒有正確釋放掉內存,系統就會覺得越來越慢,甚至不穩定。為了解決這個問題,Android引入了一個新的機制,即生命周期(Life Cycle)。
?
? ?二.六大布局:
Android六大界面布局方式:
聲明Android程序布局有兩種方式:
1) 使用XML文件描述界面布局;
2) 在Java代碼中通過調用方法進行控制。
我們既可以使用任何一種聲明界面布局的方式,也可以同時使用兩種方式。
使用XML文件聲明有以下3個特點:
·???????1) 將程序的表現層和控制層分離;
·???????2) 在后期修改用戶界面時,無須更改程序的源程序;
·???????3) 可通過WYSIWYG可視化工具直接看到所設計的用戶界面,有利于加快界面設計的過程。
建議盡量采用XML文件聲明界面元素布局。在程序運行時動態添加界面布局會大大降低應用響應速度,但依然可以在必要時動態改變屏幕內容。
六大界面布局方式包括:?線性布局(LinearLayout)、框架布局(FrameLayout)、表格布局(TableLayout)、相對布局(RelativeLayout)、絕對布局(AbsoluteLayout)和網格布局(GridLayout)?。
1.LinearLayout線性布局
LinearLayout容器中的組件一個挨一個排列,通過控制android:orientation屬性,可控制各組件是橫向排列還是縱向排列。
LinearLayout的常用XML屬性及相關方法
| XML屬性 | 相關方法 | 說明 |
| android:gravity | setGravity(int) | 設置布局管理器內組件的對齊方式 |
| android:orientation | setOrientation(int) | 設置布局管理器內組件的排列方式,可以設置為horizontal、vertical兩個值之一 |
其中,gravity屬性支持top, left, right, center_vertical, fill_vertical,center_horizontal, fill_horizontal, center, fill, clip_vertical,clip_horizontal。也可以同時指定多種對齊方式的組合。
LinearLayout子元素支持的常用XML屬性及方法
| XML屬性 | 說明 |
| android:layout_gravity | 指定該子元素在LinearLayout中的對齊方式 |
| android:layout_weight | 指定子元素在LinearLayout中所占的權重 |
2.TableLayout表格布局
TableLayout繼承自Linearout,本質上仍然是線性布局管理器。表格布局采用行、列的形式來管理UI組件,并不需要明確地聲明包含多少行、多少列,而是通過添加TableRow、其他組件來控制表格的行數和列數。
每向TableLayout中添加一個TableRow就代表一行;
每向TableRow中添加一個一個子組件就表示一列;
如果直接向TableLayout添加組件,那么該組件將直接占用一行;
在表格布局中,可以為單元格設置如下三種行為方式:
·???????Shrinkable:該列的所有單元格的寬度可以被收縮,以保證該表格能適應父容器的寬度;
·???????Strentchable:該列所有單元格的寬度可以被拉伸,以保證組件能完全填滿表格空余空間;
·???????Collapsed:如果該列被設置為Collapsed,那么該列的所有單元格會被隱藏;
TableLayout的常用XML屬性及方法
| XML屬性 | 相關方法 | 說明 |
| android:collapseColumns | setColumns(int, boolean) | 設置需要被隱藏的列的序號,多個序號間用逗號分隔 |
| android:shrinkColumns | setShrinkAllColumns(boolean) | 設置需要被收縮的列的序號 |
| android:stretchColumns | setStretchAllColumns(boolean) | 設置允許被拉伸的列的序號 |
3.FrameLayout幀布局
FrameLayout直接繼承自ViewGroup組件。幀布局為每個加入其中的組件創建一個空白的區域(稱為一幀),每個子組件占據一幀,這些幀會根據gravity屬性執行自動對齊。
FrameLayout的常用XM了屬性及方法
| XML屬性 | 相關方法 | 說明 |
| android:foreground | setForeground(Drawable) | 設置該幀布局容器的前景圖像 |
| android:foregroundGravity | setForeGroundGraity(int) | 定義繪制前景圖像的gravity屬性 |
4.RelativeLayout相對布局
RelativeLayout的XML屬性及相關方法說明
| XML屬性 | 相關方法 | 說明 |
| android:gravity | setGravity(int) | ? |
| android:ignoreGravity | setIgnoreGravity(int) | 設置哪個組件不受gravity屬性的影響 |
為了控制該布局容器的各子組件的布局分布,RelativeLayout提供了一個內部類:RelativeLayout.LayoutParams。
RelativeLayout.LayoutParams里只能設為boolean的XML屬性
| XML屬性 | 說明 |
| android:layout_centerHorizontal | 設置該子組件是否位于布局容器的水平居中 |
| android:layout_centerVertical | ? |
| android:layout_centerParent | ? |
| android:layout_alignParentBottom | ? |
| android:layout_alignParentLeft | ? |
| android:layout_alignParentRight | ? |
| android:layout_alignParentTop | ? |
RelativeLayout.LayoutParams里屬性值為其他UI組件ID的XML屬性
| XML屬性 | 說明 |
| android:layout_toRightOf | 控制該子組件位于給出ID組件的右側 |
| android:layout_toLeftOf | ? |
| android:layout_above | ? |
| android:layout_below | ? |
| android:layout_alignTop | ? |
| android:layout_alignBottom | ? |
| android:layout_alignRight | ? |
| android:layout_alignLeft | ? |
5.Android 4.0新增的網格布局GridLayout
GridLayout是Android4.0增加的網格布局控件,與之前的TableLayout有些相似,它把整個容器劃分為rows × columns個網格,每個網格可以放置一個組件。性能及功能都要比tablelayout好,比如GridLayout布局中的單元格可以跨越多行,而tablelayout則不行,此外,其渲染速度也比tablelayout要快。
GridLayout提供了setRowCount(int)和setColumnCount(int)方法來控制該網格的行和列的數量。
GridLayout常用的XML屬性和方法說明
| XML屬性 | 相關方法 | 說明 |
| android:alignmentMode | setAlignmentMode(int) | 設置該布局管理器采用的對齊模式 |
| android:columnCount | setColumnCount(int) | 設置該網格的列數量 |
| android:columnOrderPreserved | setColumnOrderPreserved(boolean) | 設置該網格容器是否保留序列號 |
| android:roeCount | setRowCount(int) | 設置該網格的行數量 |
| android:rowOrderPreserved | setRowOrderPreserved(boolean) | 設置該網格容器是否保留行序號 |
| android:useDefaultMargins | setUseDefaultMargins(boolean) | 設置該布局管理器是否使用默認的頁邊距 |
為了控制GridLayout布局容器中各子組件的布局分布,GridLayout提供了一個內部類:GridLayout.LayoutParams,來控制Gridlayout布局容器中子組件的布局分布。
GridLayout.LayoutParams常用的XML屬性和方法說明
| XML屬性 | 說明 |
| android:layout_column | 設置該組件在GridLayout的第幾列 |
| android:layout_columnSpan | 設置該子組件在GridLayout橫向上跨幾列 |
| android:layout_gravity | 設置該子組件采用何種方式占據該網格的空間 |
| android:layout_row | 設置該子組件在GridLayout的第幾行 |
| android:layout_rowSpan | 設置該子組件在GridLayout縱向上跨幾行 |
6.AbsoluteLayout絕對布局
即Android不提供任何布局控制,而是由開發人員自己通過X坐標、Y坐標來控制組件的位置。每個組件都可指定如下兩個XML屬性:
·???????layour_x;
·???????layout_y;
絕對布局已經過時,不應使用或少使用。
界面布局類型的選擇和性能優化
首先得明確,界面布局類型的嵌套越多越深越復雜,會使布局實例化變慢,使Activity的展開時間延長。建議盡量減少布局嵌套,盡量減少創建View對象的數量。
1 . 減少布局層次,可考慮用RelativeLayout來代替LinearLayout。通過Relative的相對其他元素的位置來布局,可減少塊狀嵌套;
2 . 另一種減少布局層次的技巧是使用?<merge />?標簽來合并布局;
3 . 重用布局。Android支持在XML中使用?<include />?標簽,?<include />?通過指定android:layout屬性來指定要包含的另一個XML布局。
如:
<includeandroid:id="@+id/id1"android:layout="@layout/mylayout">
<includeandroid:id="@+id/id2"android:layout="@layout/mylayout">
<includeandroid:id="@+id/id3"android:layout="@layout/mylayout">
? ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ?? ? ? ? ?三.五大存儲:
在Android中,可供選擇的存儲方式有SharedPreferences、文件存儲、SQLite數據庫方式、內容提供器(Content provider)和網絡。
一.SharedPreferences方式
???????Android提供用來存儲一些簡單的配置信息的一種機制,例如,一些默認歡迎語、登錄的用戶名和密碼等。其以鍵值對的方式存儲,
使得我們可以很方便的讀取和存入.
??????1)程序要實現的功能:
?????? 我們在Name文本框中輸入wangwu,在Password文本框中輸入123456,然后退出這個應用。我們在應用程序列表中找到這個應用,重新啟動,可以看到其使用了前面輸入的Name和Password
??????2)實現的代碼
??????布局
????????
view plaincopy to clipboard
?
???????主要實現代碼
???????
view plaincopy to clipboard
???????
?????? SharedPreferences保存到哪里去了?
???????SharedPreferences是以XML的格式以文件的方式自動保存的,在DDMS中的File Explorer中展開到/data/data/<package
name>/shared_prefs下,以上面這個為例,可以看到一個叫做SETTING_Infos.xml的文件
???????注意:Preferences只能在同一個包內使用,不能在不同的包之間使用。
二.文件存儲方式
??????在Android中,其提供了openFileInput 和 openFileOuput 方法讀取設備上的文件,下面看個例子代碼,具體如下所示:?
???????????? StringFILE_NAME = "tempfile.tmp";? //確定要操作文件的文件名
????????????FileOutputStream fos = openFileOutput(FILE_NAME, Context.MODE_PRIVATE); //初始化
????????????FileInputStream fis = openFileInput(FILE_NAME); //創建寫入流
??????上述代碼中兩個方法只支持讀取該應用目錄下的文件,讀取非其自身目錄下的文件將會拋出異常。需要提醒的是,如果調用
FileOutputStream 時指定的文件不存在,Android 會自動創建它。另外,在默認情況下,寫入的時候會覆蓋原文件內容,如果想把
新寫入的內容附加到原文件內容后,則可以指定其模式為Context.MODE_APPEND。
?
三.SQLite數據庫方式
?????SQLite是Android所帶的一個標準的數據庫,它支持SQL語句,它是一個輕量級的嵌入式數據庫。
??????1)實現的功能
?????????在這個例子里邊,我們在程序的主界面有一些按鈕,通過這些按鈕可以對數據庫進行標準的增、刪、改、查。
??????2)實現代碼
?????????所用到的字符文件
??????????
view plaincopy to clipboard
?????????布局代碼
?????????
view plaincopy to clipboard
?????????主要代碼
?????????
view plaincopy to clipboard
1. ?
四.內容提供器(Content provider)方式
?????在Android的設計“哲學”里是鼓勵開發者使用內部類的,這樣不但使用方便,而且執行效率也高。
??????1.什么是ContentProvider?
??????數據在Android當中是私有的,當然這些數據包括文件數據和數據庫數據以及一些其他類型的數據。難道兩個程序之間就沒有辦法對于數據進行交換?解決這個問題主要靠ContentProvider。
?一個Content Provider類實現了一組標準的方法接口,從而能夠讓其他的應用保存或讀取此Content Provider的各種數據類型。也就是說,一個程序可以通過實現一個ContentProvider的抽象接口將自己的數據暴露出去。外界根本看不到,也不用看到這個應用暴露的數據在應用當中是如何存儲的,或者是用數據庫存儲還是用文件存儲,還是通過網上獲得,這些一切都不重要,重要的是外界可以通過這一套標準及統一的接口和程序里的數據打交道,可以讀取程序的數據,也可以刪除程序的數據,當然,中間也會涉及一些權限的問題。
????? 下邊列舉一些較常見的接口,這些接口如下所示。
??????query(Uriuri, String[] projection, String selection, String[] selectionArgs,StringsortOrder):通過Uri進行查詢,返回一個Cursor。?
????? insert(Uriurl, ContentValues values):將一組數據插入到Uri 指定的地方。?
??????update(Uriuri, ContentValues values, String where, String[] selectionArgs):更新Uri指定位置的數據。?
????? delete(Uriurl, String where, String[] selectionArgs):刪除指定Uri并且符合一定條件的數據。
??????2.什么是ContentResolver?
????? 外界的程序通過ContentResolver接口可以訪問ContentProvider提供的數據,在Activity當中通過getContentResolver()可以得到當前應用的ContentResolver實例。
????? ContentResolver提供的接口和ContentProvider中需要實現的接口對應,主要有以下幾個。?
????? query(Uriuri, String[] projection, String selection, String[] selectionArgs,StringsortOrder):通過Uri進行查詢,返回一個Cursor。
????? insert(Uriurl, ContentValues values):將一組數據插入到Uri 指定的地方。
????? update(Uriuri, ContentValues values, String where, String[] selectionArgs):更新Uri指定位置的數據。
????? delete(Uriurl, String where, String[] selectionArgs):刪除指定Uri并且符合一定條件的數據。
?????3.ContentProvider和ContentResolver中用到的Uri?
????? 在ContentProvider和ContentResolver當中用到了Uri的形式通常有兩種,一種是指定全部數據,另一種是指定某個ID的數據。
???? 我們看下面的例子。?
?????????content://contacts/people/? 這個Uri指定的就是全部的聯系人數據。
?????????content://contacts/people/1 這個Uri指定的是ID為1的聯系人的數據。?
???? 在上邊兩個類中用到的Uri一般由3部分組成。
???????? 第一部分是:"content://"。
???????? 第二部分是要獲得數據的一個字符串片段。?
??????? 最后就是ID(如果沒有指定ID,那么表示返回全部)。
???? 由于URI通常比較長,而且有時候容易出錯,且難以理解。所以,在Android當中定義了一些輔助類,并且定義了一些常量來代替這些長字符串的使用,例如下邊的代碼:?
???? Contacts.People.CONTENT_URI (聯系人的URI)。
???? 1)實現的功能
????????在這個例子里邊,首先在系統的聯系人應用當中插入一些聯系人信息,然后把這些聯系人的名字和電話再顯示出來
???? 2)實現方法
????
view plaincopy to clipboard
五. 網絡存儲方式
?
?1.例子介紹
?????????通過郵政編碼查詢該地區的天氣預報,以POST發送的方式發送請求到webservicex.net站點,訪問WebService.webservicex.net站點上提供查詢天氣預報的服務,具體信息請參考其WSDL文檔,網址為:
http://www.webservicex.net/WeatherForecast.asmx?WSDL。
輸入:美國某個城市的郵政編碼。?
輸出:該郵政編碼對應城市的天氣預報。
2.實現步驟如下
(1)如果需要訪問外部網絡,則需要在AndroidManifest.xml文件中加入如下代碼申請權限許可:?
<!-- Permissions -->?
<uses-permission Android:name="Android.permission.INTERNET"/>?
(2)以HTTP POST的方式發送(注意:SERVER_URL并不是指WSDL的URL,而是服務本身的URL)。實現的代碼如下所示:
private static final String SERVER_URL = "http://www.webservicex.net/WeatherForecast. asmx/GetWeatherByZipCode"; //定義需要獲取的內容來源地址
HttpPost request = new HttpPost(SERVER_URL); //根據內容來源地址創建一個Http請求
// 添加一個變量?
List <NameValuePair> params = new ArrayList<NameValuePair>();?
// 設置一個華盛頓區號
params.add(new BasicNameValuePair("ZipCode","200120"));? //添加必須的參數
request.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8)); //設置參數的編碼
try {?
HttpResponse httpResponse = new DefaultHttpClient().execute(request); //發送請求并獲取反饋
// 解析返回的內容
if(httpResponse.getStatusLine().getStatusCode() != 404)??
{?
? String result = EntityUtils.toString(httpResponse.getEntity());?
? Log.d(LOG_TAG, result);?
}?
} catch (Exception e) {?
Log.e(LOG_TAG, e.getMessage());?
}?
?代碼解釋:
如上代碼使用Http從webservicex獲取ZipCode為“200120”(美國WASHINGTON D.C)的內容,其返回的內容如下:
<WeatherForecasts xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http: //www.w3.org/2001/XMLSchema-instance"xmlns="http://www.webservicex.net">?
? <Latitude>38.97571</Latitude>?
? <Longitude>77.02825</Longitude>?
? <AllocationFactor>0.024849</AllocationFactor>?
? <FipsCode>11</FipsCode>?
? <PlaceName>WASHINGTON</PlaceName>?
? <StateCode>DC</StateCode>?
? <Details>?
??? <WeatherData>?
????? <Day>Saturday, April 25,2009</Day>?
?????<WeatherImage>http://forecast.weather.gov/images/wtf/sct.jpg</WeatherImage>?
?????<MaxTemperatureF>88</MaxTemperatureF>?
?????<MinTemperatureF>57</MinTemperatureF>?
????? <MaxTemperatureC>31</MaxTemperatureC>?
?????<MinTemperatureC>14</MinTemperatureC>?
??? </WeatherData>?
??? <WeatherData>?
????? <Day>Sunday, April 26,2009</Day>?
?????<WeatherImage>http://forecast.weather.gov/images/wtf/few.jpg</WeatherImage>?
????? <MaxTemperatureF>89</MaxTemperatureF>?
?????<MinTemperatureF>60</MinTemperatureF>?
?????<MaxTemperatureC>32</MaxTemperatureC>?
?????<MinTemperatureC>16</MinTemperatureC>?
??? </WeatherData>
…
? </Details>?
</WeatherForecasts>
?
總結
- 上一篇: 一连三问 !!! 什么是内存对齐?内存对
- 下一篇: CAD导出.eps格式图