Android之四大組件、六大布局、五大存儲

一.四大組件:

        

Android四大組件分別爲activityservicecontent providerbroadcast receiver

一、android四大組件詳解

1activity

1)一個Activity通常就是一個單獨的屏幕(窗口)。

2Activity之間通過Intent進行通信。

3android應用中每一個Activity都必須要在AndroidManifest.xml配置文件中聲明,否則系統將不識別也不執行該Activity

2service

1service用於在後臺完成用戶指定的操作。service分爲兩種:

astarted(啓動):當應用程序組件(如activity)調用startService()方法啓動服務時,服務處於started狀態。

bbound(綁定):當應用程序組件調用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組件通常用於爲其他組件提供後臺服務或監控其他組件的運行狀態。

3content provider

1android平臺提供了Content Provider使一個應用程序的指定數據集提供給其他應用程序。其他應用可以通過ContentResolver類從該內容提供者中獲取或存入數據

2)只有需要在多個應用程序間共享數據是才需要內容提供者。例如,通訊錄數據被多個應用程序使用,且必須存儲在一個內容提供者中。它的好處是統一數據訪問方式。

3ContentProvider實現數據共享ContentProvider用於保存和獲取數據,並使其對所有應用程序可見。這是不同應用程序間共享數據的唯一方式,因爲android沒有提供所有應用共同訪問的公共存儲區。

4)開發人員不會直接使用ContentProvider類的對象,大多數是通過ContentResolver對象實現對ContentProvider的操作。

5ContentProvider使用URI來唯一標識其數據集,這裏的URIcontent://作爲前綴,表示該數據由ContentProvider來管理。

4broadcast receiver

1)你的應用可以使用它對外部事件進行過濾,只對感興趣的外部事件(如當電話呼入時,或者數據網絡可用時)進行接收並做出響應。廣播接收器沒有用戶界面。然而,它們可以啓動一個activityserice來響應它們收到的信息,或者用NotificationManager來通知用戶。通知可以用很多種方式來吸引用戶的注意力,例如閃動背燈、震動、播放聲音等。一般來說是在狀態欄上放一個持久的圖標,用戶可以打開它並獲取消息。

2)廣播接收者的註冊有兩種方法,分別是程序動態註冊和AndroidManifest文件中進行靜態註冊。

3)動態註冊廣播接收器特點是當用來註冊的Activity關掉後,廣播也就失效了。靜態註冊無需擔憂廣播接收器是否被關閉,只要設備是開啓狀態,廣播接收器也是打開着的。也就是說哪怕app本身未啓動,該app訂閱的廣播在觸發時也會對它起作用。

二、android四大組件總結:

14大組件的註冊

4大基本組件都需要註冊才能使用,每個ActivityserviceContent Provider都需要在AndroidManifest文件中進行配置。AndroidManifest文件中未進行聲明的activity、服務以及內容提供者將不爲系統所見,從而也就不可用。而broadcast receiver廣播接收者的註冊分靜態註冊(在AndroidManifest文件中進行配置)和通過代碼動態創建並以調用Context.registerReceiver()的方式註冊至系統。需要注意的是在AndroidManifest文件中進行配置的廣播接收者會隨系統的啓動而一直處於活躍狀態,只要接收到感興趣的廣播就會觸發(即使程序未運行)。

24大組件的激活

內容提供者的激活:當接收到ContentResolver發出的請求後,內容提供者被激活。而其它三種組件activity、服務和廣播接收器被一種叫做intent的異步消息所激活

34大組件的關閉

內容提供者僅在響應ContentResolver提出請求的時候激活。而一個廣播接收器僅在響應廣播信息的時候激活。所以,沒有必要去顯式的關閉這些組件。Activity關閉:可以通過調用它的finish()方法來關閉一個activity。服務關閉:對於通過startService()方法啓動的服務要調用Context.stopService()方法關閉服務,使用bindService()方法啓動的服務要調用Contex.unbindService()方法關閉服務。

4android中的任務(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:gravitysetGravity(int)設置佈局管理器內組件的對齊方式
android:orientationsetOrientation(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:collapseColumnssetColumns(int, boolean)設置需要被隱藏的列的序號,多個序號間用逗號分隔
android:shrinkColumnssetShrinkAllColumns(boolean)設置需要被收縮的列的序號
android:stretchColumnssetStretchAllColumns(boolean)設置允許被拉伸的列的序號

3. FrameLayout幀佈局

FrameLayout直接繼承自ViewGroup組件。幀佈局爲每個加入其中的組件創建一個空白的區域(稱爲一幀),每個子組件佔據一幀,這些幀會根據gravity屬性執行自動對齊。

FrameLayout的常用XM了屬性及方法

XML屬性相關方法說明
android:foregroundsetForeground(Drawable)設置該幀佈局容器的前景圖像
android:foregroundGravitysetForeGroundGraity(int)定義繪製前景圖像的gravity屬性

4. RelativeLayout相對佈局

RelativeLayout的XML屬性及相關方法說明

XML屬性相關方法說明
android:gravitysetGravity(int) 
android:ignoreGravitysetIgnoreGravity(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:alignmentModesetAlignmentMode(int)設置該佈局管理器採用的對齊模式
android:columnCountsetColumnCount(int)設置該網格的列數量
android:columnOrderPreservedsetColumnOrderPreserved(boolean)設置該網格容器是否保留序列號
android:roeCountsetRowCount(int)設置該網格的行數量
android:rowOrderPreservedsetRowOrderPreserved(boolean)設置該網格容器是否保留行序號
android:useDefaultMarginssetUseDefaultMargins(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佈局。

如:

<include android:id="@+id/id1" android:layout="@layout/mylayout">
<include android:id="@+id/id2" android:layout="@layout/mylayout">
<include android:id="@+id/id3" android:layout="@layout/mylayout">
  • 1
  • 2
  • 3

                                                                             三.五大存儲:

Android中,可供選擇的存儲方式有SharedPreferences、文件存儲、SQLite數據庫方式、內容提供器(Content provider)和網絡。

一.SharedPreferences方式

        Android提供用來存儲一些簡單的配置信息的一種機制,例如,一些默認歡迎語、登錄的用戶名和密碼等。其以鍵值對的方式存儲,

使得我們可以很方便的讀取和存入.

       1)程序要實現的功能:
       我們在Name文本框中輸入wangwu,在Password文本框中輸入123456,然後退出這個應用。我們在應用程序列表中找到這個應用,重新啓動,可以看到其使用了前面輸入的Name和Password

       2)實現的代碼

       佈局

        

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7.     <TextView    
  8.         android:layout_width="fill_parent"   
  9.         android:layout_height="wrap_content"   
  10.         android:text="SharedPreferences demo"  
  11.     />  
  12.       
  13.     <TextView  
  14.         android:layout_width="fill_parent"  
  15.         android:layout_height="wrap_content"  
  16.         android:text="name"  
  17.         >  
  18.     </TextView>  
  19.       
  20.     <EditText  
  21.         android:id="@+id/name"  
  22.         android:layout_width="fill_parent"  
  23.         android:layout_height="wrap_content"  
  24.         android:text=""  
  25.         >  
  26.     </EditText>  
  27.       
  28.     <TextView  
  29.         android:layout_width="fill_parent"  
  30.         android:layout_height="wrap_content"  
  31.         android:text="password"  
  32.         >  
  33.     </TextView>  
  34.       
  35.     <EditText  
  36.         android:id="@+id/password"  
  37.         android:layout_width="fill_parent"  
  38.         android:layout_height="wrap_content"  
  39.         android:password="true"  
  40.         android:text=""  
  41.         >  
  42.     </EditText>  
  43. </LinearLayout>  
 

        主要實現代碼

       

  1. package com.demo;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.SharedPreferences;  
  5. import android.os.Bundle;  
  6. import android.widget.EditText;  
  7.   
  8. public class SharedPreferencesDemo extends Activity {  
  9.       
  10.     public static final String SETTING_INFOS = "SETTING_Infos";   
  11.     public static final String NAME = "NAME";   
  12.     public static final String PASSWORD = "PASSWORD";   
  13.     private EditText field_name;  //接收用戶名的組件   
  14.     private EditText filed_pass;  //接收密碼的組件   
  15.   
  16.     @Override  
  17.     public void onCreate(Bundle savedInstanceState) {  
  18.         super.onCreate(savedInstanceState);  
  19.         setContentView(R.layout.main);  
  20.           
  21.         //Find VIew    
  22.         field_name = (EditText) findViewById(R.id.name);  //首先獲取用來輸入用戶名的組件   
  23.         filed_pass = (EditText) findViewById(R.id.password); //同時也需要獲取輸入密碼的組件   
  24.   
  25.         // Restore preferences   
  26.         SharedPreferences settings = getSharedPreferences(SETTING_INFOS, 0); //獲取一個SharedPreferences對象   
  27.         String name = settings.getString(NAME, "");  //取出保存的NAME   
  28.         String password = settings.getString(PASSWORD, ""); //取出保存的PASSWORD   
  29.   
  30.         //Set value   
  31.         field_name.setText(name);  //將取出來的用戶名賦予field_name   
  32.         filed_pass.setText(password);  //將取出來的密碼賦予filed_pass   
  33.     }  
  34.       
  35.     @Override   
  36.     protected void onStop(){   
  37.         super.onStop();   
  38.           
  39.         SharedPreferences settings = getSharedPreferences(SETTING_INFOS, 0); //首先獲取一個SharedPreferences對象   
  40.         settings.edit()   
  41.                 .putString(NAME, field_name.getText().toString())   
  42.                 .putString(PASSWORD, filed_pass.getText().toString())   
  43.                 .commit();   
  44.     } //將用戶名和密碼保存進去   
  45.   
  46. }  
       
       SharedPreferences保存到哪裏去了?

       SharedPreferences是以XML的格式以文件的方式自動保存的,在DDMS中的File Explorer中展開到/data/data/<package

name>/shared_prefs下,以上面這個爲例,可以看到一個叫做SETTING_Infos.xml的文件

       注意:Preferences只能在同一個包內使用,不能在不同的包之間使用。

二.文件存儲方式

       在Android中,其提供了openFileInput 和 openFileOuput 方法讀取設備上的文件,下面看個例子代碼,具體如下所示: 
             String FILE_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)實現代碼

          所用到的字符文件

          

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.     <string name="app_name">SQLite數據庫操作實例</string>  
  4.     <string name="button1">建立數據庫表</string>  
  5.     <string name="button2">刪除數據庫表</string>  
  6.     <string name="button3">插入兩條記錄</string>  
  7.     <string name="button4">刪除一條記錄</string>  
  8.     <string name="button5">查看數據庫表</string>  
  9. </resources>  

          佈局代碼

         

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7.       
  8.     <TextView    
  9.         android:layout_width="fill_parent"   
  10.         android:layout_height="wrap_content"   
  11.         android:text="@string/app_name"  
  12.     />  
  13.     <Button   
  14.         android:text="@string/button1"   
  15.         android:id="@+id/button1"   
  16.         android:layout_width="wrap_content"   
  17.         android:layout_height="wrap_content"  
  18.         ></Button>  
  19.     <Button   
  20.         android:text="@string/button2"   
  21.         android:id="@+id/button2"   
  22.         android:layout_width="wrap_content"   
  23.         android:layout_height="wrap_content"  
  24.         ></Button>  
  25.     <Button   
  26.         android:text="@string/button3"   
  27.         android:id="@+id/button3"   
  28.         android:layout_width="wrap_content"   
  29.         android:layout_height="wrap_content"  
  30.         ></Button>  
  31.     <Button   
  32.         android:text="@string/button4"   
  33.         android:id="@+id/button4"   
  34.         android:layout_width="wrap_content"   
  35.         android:layout_height="wrap_content"  
  36.         ></Button>  
  37.     <Button   
  38.         android:text="@string/button5"   
  39.         android:id="@+id/button5"   
  40.         android:layout_width="wrap_content"   
  41.         android:layout_height="wrap_content"  
  42.         ></Button>  
  43.   
  44. </LinearLayout>  

          主要代碼

         

  1. package com.sqlite;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.Context;  
  5. import android.database.Cursor;  
  6. import android.database.SQLException;  
  7. import android.database.sqlite.SQLiteDatabase;  
  8. import android.database.sqlite.SQLiteOpenHelper;  
  9. import android.os.Bundle;  
  10. import android.util.Log;  
  11. import android.view.View;  
  12. import android.view.View.OnClickListener;  
  13. import android.widget.Button;  
  14.   
  15. /* 
  16.  * 什麼是SQLiteDatabase? 
  17.  * 一個SQLiteDatabase的實例代表了一個SQLite的數據庫,通過SQLiteDatabase實例的一些方法,我們可以執行SQL語句, 
  18.  * 對數據庫進行增、刪、查、改的操作。需要注意的是,數據庫對於一個應用來說是私有的,並且在一個應用當中,數據庫的名字也是惟一的。  
  19.  */  
  20.   
  21. /* 
  22.  * 什麼是SQLiteOpenHelper ?  
  23.  * 這個類主要生成一個數據庫,並對數據庫的版本進行管理。 
  24.  * 當在程序當中調用這個類的方法getWritableDatabase()或者getReadableDatabase()方法的時候,如果當時沒有數據,那麼Android系統就會自動生成一個數據庫。 
  25.  * SQLiteOpenHelper 是一個抽象類,我們通常需要繼承它,並且實現裏邊的3個函數, 
  26.  *     onCreate(SQLiteDatabase):在數據庫第一次生成的時候會調用這個方法,一般我們在這個方法裏邊生成數據庫表。 
  27.  *     onUpgrade(SQLiteDatabase, int, int):當數據庫需要升級的時候,Android系統會主動的調用這個方法。一般我們在這個方法裏邊刪除數據表,並建立新的數據表,當然是否還需要做其他的操作,完全取決於應用的需求。 
  28.  *     onOpen(SQLiteDatabase):這是當打開數據庫時的回調函數,一般也不會用到。  
  29.  */  
  30.   
  31. public class SQLiteDemo extends Activity {  
  32.       
  33.     OnClickListener listener1 = null;  
  34.     OnClickListener listener2 = null;  
  35.     OnClickListener listener3 = null;  
  36.     OnClickListener listener4 = null;  
  37.     OnClickListener listener5 = null;  
  38.   
  39.     Button button1;  
  40.     Button button2;  
  41.     Button button3;  
  42.     Button button4;  
  43.     Button button5;  
  44.   
  45.     DatabaseHelper mOpenHelper;  
  46.   
  47.     private static final String DATABASE_NAME = "dbForTest.db";  
  48.     private static final int DATABASE_VERSION = 1;  
  49.     private static final String TABLE_NAME = "diary";  
  50.     private static final String TITLE = "title";  
  51.     private static final String BODY = "body";  
  52.   
  53.     //建立一個內部類,主要生成一個數據庫   
  54.     private static class DatabaseHelper extends SQLiteOpenHelper {  
  55.           
  56.         DatabaseHelper(Context context) {  
  57.             super(context, DATABASE_NAME, null, DATABASE_VERSION);  
  58.         }  
  59.   
  60.         //在數據庫第一次生成的時候會調用這個方法,一般我們在這個方法裏邊生成數據庫表。   
  61.         @Override  
  62.         public void onCreate(SQLiteDatabase db) {  
  63.   
  64.             String sql = "CREATE TABLE " + TABLE_NAME + " (" + TITLE  
  65.                     + " text not null, " + BODY + " text not null " + ");";  
  66.             Log.i("haiyang:createDB=", sql);  
  67.             db.execSQL(sql);  
  68.         }  
  69.   
  70.         @Override  
  71.         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {  
  72.         }  
  73.     }  
  74.   
  75.     @Override  
  76.     public void onCreate(Bundle savedInstanceState) {  
  77.         super.onCreate(savedInstanceState);  
  78.         setContentView(R.layout.main);  
  79.         prepareListener();  
  80.         initLayout();  
  81.         mOpenHelper = new DatabaseHelper(this);  
  82.   
  83.     }  
  84.   
  85.     private void initLayout() {  
  86.         button1 = (Button) findViewById(R.id.button1);  
  87.         button1.setOnClickListener(listener1);  
  88.   
  89.         button2 = (Button) findViewById(R.id.button2);  
  90.         button2.setOnClickListener(listener2);  
  91.   
  92.         button3 = (Button) findViewById(R.id.button3);  
  93.         button3.setOnClickListener(listener3);  
  94.           
  95.         button4 = (Button) findViewById(R.id.button4);  
  96.         button4.setOnClickListener(listener4);  
  97.   
  98.         button5 = (Button) findViewById(R.id.button5);  
  99.         button5.setOnClickListener(listener5);  
  100.   
  101.     }  
  102.   
  103.     private void prepareListener() {  
  104.         listener1 = new OnClickListener() {  
  105.             public void onClick(View v) {  
  106.                 CreateTable();  
  107.             }  
  108.         };  
  109.         listener2 = new OnClickListener() {  
  110.             public void onClick(View v) {  
  111.                 dropTable();  
  112.             }  
  113.         };  
  114.         listener3 = new OnClickListener() {  
  115.             public void onClick(View v) {  
  116.                 insertItem();  
  117.             }  
  118.         };  
  119.         listener4 = new OnClickListener() {  
  120.             public void onClick(View v) {  
  121.                 deleteItem();  
  122.             }  
  123.         };  
  124.         listener5 = new OnClickListener() {  
  125.             public void onClick(View v) {  
  126.                 showItems();  
  127.             }  
  128.         };  
  129.     }  
  130.   
  131.     /* 
  132.      * 重新建立數據表 
  133.      */  
  134.     private void CreateTable() {  
  135.         //mOpenHelper.getWritableDatabase()語句負責得到一個可寫的SQLite數據庫,如果這個數據庫還沒有建立,   
  136.         //那麼mOpenHelper輔助類負責建立這個數據庫。如果數據庫已經建立,那麼直接返回一個可寫的數據庫。   
  137.         SQLiteDatabase db = mOpenHelper.getWritableDatabase();  
  138.         String sql = "CREATE TABLE " + TABLE_NAME + " (" + TITLE  
  139.                 + " text not null, " + BODY + " text not null " + ");";  
  140.         Log.i("haiyang:createDB=", sql);  
  141.   
  142.         try {  
  143.             db.execSQL("DROP TABLE IF EXISTS diary");  
  144.             db.execSQL(sql);  
  145.             setTitle("數據表成功重建");  
  146.         } catch (SQLException e) {  
  147.             setTitle("數據表重建錯誤");  
  148.         }  
  149.     }  
  150.   
  151.     /* 
  152.      * 刪除數據表 
  153.      */  
  154.     private void dropTable() {  
  155.         //mOpenHelper.getWritableDatabase()語句負責得到一個可寫的SQLite數據庫,如果這個數據庫還沒有建立,   
  156.         //那麼mOpenHelper輔助類負責建立這個數據庫。如果數據庫已經建立,那麼直接返回一個可寫的數據庫。   
  157.         SQLiteDatabase db = mOpenHelper.getWritableDatabase();  
  158.         String sql = "drop table " + TABLE_NAME;  
  159.         try {  
  160.             db.execSQL(sql);  
  161.             setTitle("數據表成功刪除:" + sql);  
  162.         } catch (SQLException e) {  
  163.             setTitle("數據表刪除錯誤");  
  164.         }  
  165.     }  
  166.   
  167.     /* 
  168.      * 插入兩條數據 
  169.      */  
  170.     private void insertItem() {  
  171.         //mOpenHelper.getWritableDatabase()語句負責得到一個可寫的SQLite數據庫,如果這個數據庫還沒有建立,   
  172.         //那麼mOpenHelper輔助類負責建立這個數據庫。如果數據庫已經建立,那麼直接返回一個可寫的數據庫。   
  173.         SQLiteDatabase db = mOpenHelper.getWritableDatabase();  
  174.         String sql1 = "insert into " + TABLE_NAME + " (" + TITLE + ", " + BODY  
  175.                 + ") values('haiyang', 'android的發展真是迅速啊');";  
  176.         String sql2 = "insert into " + TABLE_NAME + " (" + TITLE + ", " + BODY  
  177.                 + ") values('icesky', 'android的發展真是迅速啊');";  
  178.         try {  
  179.             // Log.i()會將參數內容打印到日誌當中,並且打印級別是Info級別   
  180.             // Android支持5種打印級別,分別是Verbose、Debug、Info、Warning、Error,當然我們在程序當中一般用到的是Info級別   
  181.             Log.i("haiyang:sql1=", sql1);  
  182.             Log.i("haiyang:sql2=", sql2);  
  183.             db.execSQL(sql1);  
  184.             db.execSQL(sql2);  
  185.             setTitle("插入兩條數據成功");  
  186.         } catch (SQLException e) {  
  187.             setTitle("插入兩條數據失敗");  
  188.         }  
  189.     }  
  190.   
  191.     /* 
  192.      * 刪除其中的一條數據 
  193.      */  
  194.     private void deleteItem() {  
  195.         try {  
  196.             //mOpenHelper.getWritableDatabase()語句負責得到一個可寫的SQLite數據庫,如果這個數據庫還沒有建立,   
  197.             //那麼mOpenHelper輔助類負責建立這個數據庫。如果數據庫已經建立,那麼直接返回一個可寫的數據庫。   
  198.             SQLiteDatabase db = mOpenHelper.getWritableDatabase();  
  199.             //第一個參數是數據庫表名,在這裏是TABLE_NAME,也就是diary。    
  200.             //第二個參數,相當於SQL語句當中的where部分,也就是描述了刪除的條件。   
  201.             //如果在第二個參數當中有“?”符號,那麼第三個參數中的字符串會依次替換在第二個參數當中出現的“?”符號。    
  202.             db.delete(TABLE_NAME, " title = 'haiyang'"null);  
  203.             setTitle("刪除title爲haiyang的一條記錄");  
  204.         } catch (SQLException e) {  
  205.   
  206.         }  
  207.   
  208.     }  
  209.   
  210.     /* 
  211.      * 在屏幕的title區域顯示當前數據表當中的數據的條數。 
  212.      */  
  213.     /* 
  214.      * Cursor cur = db.query(TABLE_NAME, col, null, null, null, null, null)語句將查詢到的數據放到一個Cursor 當中。 
  215.         這個Cursor裏邊封裝了這個數據表TABLE_NAME當中的所有條列。  
  216.         query()方法相當的有用,在這裏我們簡單地講一下。 
  217.             第一個參數是數據庫裏邊表的名字,比如在我們這個例子,表的名字就是TABLE_NAME,也就是"diary"。 
  218.             第二個字段是我們想要返回數據包含的列的信息。在這個例子當中我們想要得到的列有title、body。我們把這兩個列的名字放到字符串數組裏邊來。 
  219.             第三個參數爲selection,相當於SQL語句的where部分,如果想返回所有的數據,那麼就直接置爲null。 
  220.             第四個參數爲selectionArgs。在selection部分,你有可能用到“?”,那麼在selectionArgs定義的字符串會代替selection中的“?”。 
  221.             第五個參數爲groupBy。定義查詢出來的數據是否分組,如果爲null則說明不用分組。 
  222.             第六個參數爲having ,相當於SQL語句當中的having部分。 
  223.             第七個參數爲orderBy,來描述我們期望的返回值是否需要排序,如果設置爲null則說明不需要排序。 
  224.      */  
  225.       
  226.     private void showItems() {  
  227.   
  228.         SQLiteDatabase db = mOpenHelper.getReadableDatabase();  
  229.         String col[] = { TITLE, BODY };  
  230.         //查詢數據   
  231.         Cursor cur = db.query(TABLE_NAME, col, nullnullnullnullnull);  
  232.         Integer num = cur.getCount();  
  233.         setTitle(Integer.toString(num) + " 條記錄");  
  234.     }  
  235. }   cop 

四.內容提供器(Content provider)方式

      在Android的設計“哲學”裏是鼓勵開發者使用內部類的,這樣不但使用方便,而且執行效率也高。

      1.什麼是ContentProvider 
      數據在Android當中是私有的,當然這些數據包括文件數據和數據庫數據以及一些其他類型的數據。難道兩個程序之間就沒有辦法對於數據進行交換?解決這個問題主要靠ContentProvider。
 一個Content Provider類實現了一組標準的方法接口,從而能夠讓其他的應用保存或讀取此Content Provider的各種數據類型。也就是說,一個程序可以通過實現一個Content Provider的抽象接口將自己的數據暴露出去。外界根本看不到,也不用看到這個應用暴露的數據在應用當中是如何存儲的,或者是用數據庫存儲還是用文件存儲,還是通過網上獲得,這些一切都不重要,重要的是外界可以通過這一套標準及統一的接口和程序裏的數據打交道,可以讀取程序的數據,也可以刪除程序的數據,當然,中間也會涉及一些權限的問題。
      下邊列舉一些較常見的接口,這些接口如下所示。
      query(Uri uri, String[] projection, String selection, String[] selectionArgs,String sortOrder):通過Uri進行查詢,返回一個Cursor。 
      insert(Uri url, ContentValues values):將一組數據插入到Uri 指定的地方。 
      update(Uri uri, ContentValues values, String where, String[] selectionArgs):更新Uri指定位置的數據。 
      delete(Uri url, String where, String[] selectionArgs):刪除指定Uri並且符合一定條件的數據。

      2.什麼是ContentResolver 
      外界的程序通過ContentResolver接口可以訪問ContentProvider提供的數據,在Activity當中通過getContentResolver()可以得到當前應用的ContentResolver實例。
      ContentResolver提供的接口和ContentProvider中需要實現的接口對應,主要有以下幾個。 
      query(Uri uri, String[] projection, String selection, String[] selectionArgs,String sortOrder):通過Uri進行查詢,返回一個Cursor。
      insert(Uri url, ContentValues values):將一組數據插入到Uri 指定的地方。
      update(Uri uri, ContentValues values, String where, String[] selectionArgs):更新Uri指定位置的數據。
      delete(Uri url, 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)實現方法

    

  1. package com.contentProvider;  
  2.   
  3. import android.app.ListActivity;  
  4. import android.database.Cursor;  
  5. import android.os.Bundle;  
  6. import android.provider.Contacts.Phones;  
  7. import android.widget.ListAdapter;  
  8. import android.widget.SimpleCursorAdapter;  
  9.   
  10. public class ContentProviderDemo extends ListActivity {  
  11.       
  12.     protected void onCreate(Bundle savedInstanceState) {  
  13.         super.onCreate(savedInstanceState);  
  14.         //getContentResolver()方法得到應用的ContentResolver實例。   
  15.         // query(Phones.CONTENT_URI, null, null, null, null)。它是ContentResolver裏的方法,負責查詢所有聯繫人,並返回一個Cursor。這個方法參數比較多,每個參數的具體含義如下。   
  16.         //·  第一個參數爲Uri,在這個例子裏邊這個Uri是聯繫人的Uri。   
  17.         //·  第二個參數是一個字符串的數組,數組裏邊的每一個字符串都是數據表中某一列的名字,它指定返回數據表中那些列的值。   
  18.         //·  第三個參數相當於SQL語句的where部分,描述哪些值是我們需要的。   
  19.         //·  第四個參數是一個字符串數組,它裏邊的值依次代替在第三個參數中出現的“?”符號。   
  20.         //·  第五個參數指定了排序的方式。   
  21.         Cursor c = getContentResolver().query(Phones.CONTENT_URI, nullnullnullnull);  
  22.         startManagingCursor(c); //讓系統來管理生成的Cursor。   
  23.         ListAdapter adapter = new SimpleCursorAdapter(  
  24.                 this,  
  25.                 android.R.layout.simple_list_item_2,   
  26.                 c,   
  27.                 new String[] { Phones.NAME, Phones.NUMBER },   
  28.                 new int[] { android.R.id.text1, android.R.id.text2 });  
  29.         setListAdapter(adapter); //將ListView和SimpleCursorAdapter進行綁定。   
  30.     }  
  31.       
  32. }  

五. 網絡存儲方式

 

 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>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章