Android應用開發(fā)之進階知識介紹_第1頁
Android應用開發(fā)之進階知識介紹_第2頁
Android應用開發(fā)之進階知識介紹_第3頁
Android應用開發(fā)之進階知識介紹_第4頁
Android應用開發(fā)之進階知識介紹_第5頁
已閱讀5頁,還剩47頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

Android應用開發(fā)——進階知識應用綱要數(shù)據(jù)存儲與IO深入理解ActivityAndroid網絡應用BroadcastReceiver應用效勞——service通知管理——Notification數(shù)據(jù)存儲與IO文件存儲SharedPreferencesSqlite數(shù)據(jù)庫ContentProvider文件存儲提供了openFileOutput()和openFileInput()方法進行IO操作。openFileOutput()首先給大家介紹使用文件如何對數(shù)據(jù)進行存儲,Activity提供了openFileOutput()方法可以用于把數(shù)據(jù)輸出到文件中,具體的實現(xiàn)過程與在J2SE環(huán)境中保存數(shù)據(jù)到文件中是一樣的。privatevoidwrite(Stringcontent) { try { //以追加模式翻開文件輸出流 FileOutputStreamfos=openFileOutput(FILE_NAME,MODE_APPEND); //將FileOutputStream包裝成PrintStream PrintStreamps=newPrintStream(fos); //輸出文件內容 ps.println(content); //關閉文件輸出流 ps.close(); } catch(Exceptione) { e.printStackTrace(); } }文件存儲openFileOutput()openFileOutput()方法的第一參數(shù)用于指定文件名稱,不能包含路徑分隔符“/”,如果文件不存在,Android會自動創(chuàng)立它。創(chuàng)立的文件保存在/data/data/<packagename>/files目錄,如:,通過點擊Eclipse菜單“Window”-“ShowView”-“Other”,在對話窗口中展開android文件夾,選擇下面的FileExplorer視圖,然后在FileExplorer視圖中展開/data/data/<packagename>/files目錄就可以看到該文件。openFileOutput()方法的第二參數(shù)用于指定操作模式,有四種模式,分別為:Context.MODE_PRIVATE=0Context.MODE_APPEND=32768Context.MODE_WORLD_READABLE=1Context.MODE_WORLD_WRITEABLE=2文件存儲openFileOutput()Context.MODE_PRIVATE:為默認操作模式,代表該文件是私有數(shù)據(jù),只能被應用本身訪問,在該模式下,寫入的內容會覆蓋原文件的內容,如果想把新寫入的內容追加到原文件中。可以使用Context.MODE_APPENDContext.MODE_APPEND:模式會檢查文件是否存在,存在就往文件追加內容,否那么就創(chuàng)立新文件。Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE用來控制其他應用是否有權限讀寫該文件。MODE_WORLD_READABLE:表示當前文件可以被其他應用讀??;MODE_WORLD_WRITEABLE:表示當前文件可以被其他應用寫入。如果希望文件被其他應用讀和寫,可以傳入:openFileOutput("itcast.txt",Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE);android有一套自己的平安模型,當應用程序(.apk)在安裝時系統(tǒng)就會分配給他一個userid,當該應用要去訪問其他資源比方文件的時候,就需要userid匹配。默認情況下,任何應用創(chuàng)立的文件,sharedpreferences,數(shù)據(jù)庫都應該是私有的〔位于/data/data/<packagename>/files〕,其他程序無法訪問。除非在創(chuàng)立時指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE,只有這樣其他程序才能正確訪問。文件存儲openFileInput()如果要翻開存放在/data/data/<packagename>/files目錄應用私有的文件,可以使用Activity提供openFileInput()方法。privateStringread() { try { //翻開文件輸入流 FileInputStreamfis=openFileInput(FILE_NAME); byte[]buff=newbyte[1024]; inthasRead=0; StringBuildersb=newStringBuilder(""); //讀取文件內容 while((hasRead=fis.read(buff))>0) { sb.append(newString(buff,0,hasRead)); } //關閉文件輸入流 fis.close(); returnsb.toString(); } catch(Exceptione) { e.printStackTrace(); } returnnull; }文件存儲openFileInput()或者直接使用文件的絕對路徑:Filefile=newFile("/data/data//files/itcast.txt");FileInputStreaminStream=newFileInputStream(file);Log.i("FileTest",readInStream(inStream));注意:上面文件路徑中的“cn.itcast.action”為應用所在包,當你在編寫代碼時應替換為你自己應用使用的包。對于私有文件只能被創(chuàng)立該文件的應用訪問,如果希望文件能被其他應用讀和寫,可以在創(chuàng)立文件時,指定Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE權限。Activity還提供了getCacheDir()和getFilesDir()方法:getCacheDir()方法用于獲取/data/data/<packagename>/cache目錄getFilesDir()方法用于獲取/data/data/<packagename>/files目錄SharedPreferences很多時候我們開發(fā)的軟件需要向用戶提供軟件參數(shù)設置功能,例如我們常用的QQ,用戶可以設置是否允許陌生人添加自己為好友。對于軟件配置參數(shù)的保存,如果是window軟件通常我們會采用ini文件進行保存,如果是j2se應用,我們會采用properties屬性文件進行保存。如果是Android應用,我們最適合采用什么方式保存軟件配置參數(shù)呢?Android平臺給我們提供了一個SharedPreferences類,它是一個輕量級的存儲類,特別適合用于保存軟件配置參數(shù)。使用SharedPreferences保存數(shù)據(jù),其背后是用xml文件存放數(shù)據(jù),文件存放在/data/data/<packagename>/shared_prefs目錄下:SharedPreferencessharedPreferences=getSharedPreferences("itcast",Context.MODE_PRIVATE);Editoreditor=sharedPreferences.edit();//獲取編輯器editor.putString("name","jack");editor.putInt("age",4);editormit();//提交修改生成的itcast.xml文件內容如下:<?xmlversion='1.0'encoding='utf-8'standalone='yes'?><map><stringname="name">Jack</string><intname="age"value="4"/></map>因為SharedPreferences背后是使用xml文件保存數(shù)據(jù),getSharedPreferences(name,mode)方法的第一個參數(shù)用于指定該文件的名稱,名稱不用帶后綴,后綴會由Android自動加上。方法的第二個參數(shù)指定文件的操作模式,共有四種操作模式,這四種模式前面介紹使用文件方式保存數(shù)據(jù)時已經講解過。如果希望SharedPreferences背后使用的xml文件能被其他應用讀和寫,可以指定Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE權限。另外Activity還提供了另一個getPreferences(mode)方法操作SharedPreferences,這個方法默認使用當前類不帶包名的類名作為文件的名稱。SharedPreferences訪問SharedPreferences中的數(shù)據(jù)代碼如下:SharedPreferencessharedPreferences=getSharedPreferences("itcast",Context.MODE_PRIVATE);//getString()第二個參數(shù)為缺省值,如果preference中不存在該key,將返回缺省值Stringname=sharedPreferences.getString("name","");intage=sharedPreferences.getInt("age",1);如果訪問其他應用中的Preference,前提條件是:該preference創(chuàng)立時指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE權限。如:有個<packagename>為的應用使用下面語句創(chuàng)立了preference。getSharedPreferences("itcast",Context.MODE_WORLD_READABLE);其他應用要訪問上面應用的preference,首先需要創(chuàng)立上面應用的Context,然后通過Context訪問preference,訪問preference時會在應用所在包下的shared_prefs目錄找到preference:ContextotherAppsContext=createPackageContext("cn.itcast.action",Context.CONTEXT_IGNORE_SECURITY);SharedPreferencessharedPreferences=otherAppsContext.getSharedPreferences("itcast",Context.MODE_WORLD_READABLE);Stringname=sharedPreferences.getString("name","");intage=sharedPreferences.getInt("age",0);如果不通過創(chuàng)立Context訪問其他應用的preference,可以以讀取xml文件方式直接訪問其他應用preference對應的xml文件,如:FilexmlFile=newFile(“/data/data/<packagename>/shared_prefs/itcast.xml”);//<packagename>應替換成應用的包名SQLite數(shù)據(jù)庫除了可以使用文件或SharedPreferences存儲數(shù)據(jù),還可以選擇使用SQLite數(shù)據(jù)庫存儲數(shù)據(jù)。在Android平臺上,集成了一個嵌入式關系型數(shù)據(jù)庫—SQLite,SQLite3支持NULL、INTEGER、REAL〔浮點數(shù)字〕、TEXT(字符串文本)和BLOB(二進制對象)數(shù)據(jù)類型,雖然它支持的類型雖然只有五種,但實際上sqlite3也接受varchar(n)、char(n)、decimal(p,s)等數(shù)據(jù)類型,只不過在運算或保存時會轉成對應的五種數(shù)據(jù)類型。SQLite最大的特點是你可以保存任何類型的數(shù)據(jù)到任何字段中,無論這列聲明的數(shù)據(jù)類型是什么。例如:可以在Integer字段中存放字符串,或者在布爾型字段中存放浮點數(shù),或者在字符型字段中存放日期型值。但有一種情況例外:定義為INTEGERPRIMARYKEY的字段只能存儲64位整數(shù),當向這種字段中保存除整數(shù)以外的數(shù)據(jù)時,將會產生錯誤。另外,SQLite在解析CREATETABLE語句時,會忽略CREATETABLE語句中跟在字段名后面的數(shù)據(jù)類型信息,如下面語句會忽略name字段的類型信息:CREATETABLEperson(personidintegerprimarykeyautoincrement,namevarchar(20))SQLite可以解析大局部標準SQL語句,如:查詢語句:select*from表名where條件子句groupby分組字句having...orderby排序子句如:select*frompersonselect*frompersonorderbyiddescselectnamefrompersongroupbynamehavingcount(*)>1分頁SQL與mysql類似,下面SQL語句獲取5條記錄,跳過前面3條記錄select*fromAccountlimit5offset3或者select*fromAccountlimit3,5插入語句:insertinto表名(字段列表)values(值列表)。如:insertintoperson(name,age)values(‘Jack’,3)更新語句:update表名set字段名=值where條件子句。如:updatepersonsetname=‘Jack‘whereid=10刪除語句:deletefrom表名where條件子句。如:deletefrompersonwhereid=10使用SQLiteDatabase操作SQLite數(shù)據(jù)庫Android提供了一個名為SQLiteDatabase的類,該類封裝了一些操作數(shù)據(jù)庫的API,使用該類可以完成對數(shù)據(jù)進行添加(Create)、查詢(Retrieve)、更新(Update)和刪除(Delete)操作〔這些操作簡稱為CRUD〕。對SQLiteDatabase的學習,我們應該重點掌握execSQL()和rawQuery()方法。execSQL()方法可以執(zhí)行insert、delete、update和CREATETABLE之類有更改行為的SQL語句;rawQuery()方法可以執(zhí)行select語句。execSQL()方法的使用例子:SQLiteDatabasedb=....;db.execSQL("insertintoperson(name,age)values('傳智播客',4)");db.close();執(zhí)行上面SQL語句會往person表中添加進一條記錄,在實際應用中,語句中的“傳智播客”這些參數(shù)值應該由用戶輸入界面提供,如果把用戶輸入的內容原樣組拼到上面的insert語句,當用戶輸入的內容含有單引號時,組拼出來的SQL語句就會存在語法錯誤。要解決這個問題需要對單引號進行轉義,也就是把單引號轉換成兩個單引號。有些時候用戶往往還會輸入像“&”這些特殊SQL符號,為保證組拼好的SQL語句語法正確,必須對SQL語句中的這些特殊SQL符號都進行轉義,顯然,對每條SQL語句都做這樣的處理工作是比較煩瑣的。SQLiteDatabase類提供了一個重載后的execSQL(Stringsql,Object[]bindArgs)方法,使用這個方法可以解決前面提到的問題,因為這個方法支持使用占位符參數(shù)(?)。使用例子如下:SQLiteDatabasedb=....;db.execSQL("insertintoperson(name,age)values(?,?)",newObject[]{"傳智播客",4});db.close();execSQL(Stringsql,Object[]bindArgs)方法的第一個參數(shù)為SQL語句,第二個參數(shù)為SQL語句中占位符參數(shù)的值,參數(shù)值在數(shù)組中的順序要和占位符的位置對應。使用SQLiteDatabase操作SQLite數(shù)據(jù)庫使用SQLiteDatabase操作SQLite數(shù)據(jù)庫SQLiteDatabase的rawQuery()用于執(zhí)行select語句,使用例子如下:

SQLiteDatabasedb=....;Cursorcursor=db.rawQuery(“select*fromperson”,null);while(cursor.moveToNext()){ intpersonid=cursor.getInt(0);//獲取第一列的值,第一列的索引從0開始 Stringname=cursor.getString(1);//獲取第二列的值 intage=cursor.getInt(2);//獲取第三列的值}cursor.close();db.close();rawQuery()方法的第一個參數(shù)為select語句;第二個參數(shù)為select語句中占位符參數(shù)的值,如果select語句沒有使用占位符,該參數(shù)可以設置為null。帶占位符參數(shù)的select語句使用例子如下:Cursorcursor=db.rawQuery("select*frompersonwherenamelike?andage=?",newString[]{"%Jack%","4"});Cursor是結果集游標,用于對結果集進行隨機訪問,如果大家熟悉jdbc,其實Cursor與JDBC中的ResultSet作用很相似。使用moveToNext()方法可以將游標從當前行移動到下一行,如果已經移過了結果集的最后一行,返回結果為false,否那么為true。另外Cursor還有常用的moveToPrevious()方法〔用于將游標從當前行移動到上一行,如果已經移過了結果集的第一行,返回值為false,否那么為true〕、moveToFirst()方法〔用于將游標移動到結果集的第一行,如果結果集為空,返回值為false,否那么為true〕和moveToLast()方法〔用于將游標移動到結果集的最后一行,如果結果集為空,返回值為false,否那么為true〕。使用SQLiteDatabase操作SQLite數(shù)據(jù)庫使用SQLiteDatabase操作SQLite數(shù)據(jù)庫除了前面給大家介紹的execSQL()和rawQuery()方法,SQLiteDatabase還專門提供了對應于添加、刪除、更新、查詢的操作方法:insert()、delete()、update()和query()。這些方法實際上是給那些不太了解SQL語法的菜鳥使用的,對于熟悉SQL語法的程序員而言,直接使用execSQL()和rawQuery()方法執(zhí)行SQL語句就能完成數(shù)據(jù)的添加、刪除、更新、查詢操作。Insert()方法用于添加數(shù)據(jù),各個字段的數(shù)據(jù)使用ContentValues進行存放。ContentValues類似于MAP,相對于MAP,它提供了存取數(shù)據(jù)對應的put(Stringkey,Xxxvalue)和getAsXxx(Stringkey)方法,key為字段名稱,value為字段值,Xxx指的是各種常用的數(shù)據(jù)類型,如:String、Integer等。SQLiteDatabasedb=databaseHelper.getWritableDatabase();ContentValuesvalues=newContentValues();values.put("name","傳智播客");values.put("age",4);longrowid=db.insert(“person”,null,values);//返回新添記錄的行號,與主鍵id無關不管第三個參數(shù)是否包含數(shù)據(jù),執(zhí)行Insert()方法必然會添加一條記錄,如果第三個參數(shù)為空,會添加一條除主鍵之外其他字段值為Null的記錄。Insert()方法內部實際上通過構造insert語句完成數(shù)據(jù)的添加,Insert()方法的第二個參數(shù)用于指定空值字段的名稱,相信大家對此參數(shù)會感到疑惑,此參數(shù)的作用是干嘛的?是這樣的:如果第三個參數(shù)values為Null或者元素個數(shù)為0,Insert()方法必然要添加一條除了主鍵之外其它字段為Null值的記錄,為了滿足這條insert語句的語法,insert語句必須給定一個字段名,如:insertintoperson(name)values(NULL),倘假設不給定字段名,insert語句就成了這樣:insertintoperson()values(),顯然這不滿足標準SQL的語法。對于字段名,建議使用主鍵之外的字段,如果使用了INTEGER類型的主鍵字段,執(zhí)行類似insertintoperson(personid)values(NULL)的insert語句后,該主鍵字段值也不會為NULL。如果第三個參數(shù)values不為Null并且元素的個數(shù)大于0,可以把第二個參數(shù)設置為null。使用SQLiteDatabase操作SQLite數(shù)據(jù)庫使用SQLiteDatabase操作SQLite數(shù)據(jù)庫delete()方法的使用:SQLiteDatabasedb=databaseHelper.getWritableDatabase();db.delete("person","personid<?",newString[]{"2"});db.close();上面代碼用于從person表中刪除personid小于2的記錄。update()方法的使用:SQLiteDatabasedb=databaseHelper.getWritableDatabase();ContentValuesvalues=newContentValues();values.put(“name”,“Jack”);//key為字段名,value為值db.update("person",values,"personid=?",newString[]{"1"});db.close();上面代碼用于把person表中personid等于1的記錄的name字段的值改為“Jack”。使用SQLiteDatabase操作SQLite數(shù)據(jù)庫使用SQLiteDatabase操作SQLite數(shù)據(jù)庫query()方法實際上是把select語句拆分成了假設干個組成局部,然后作為方法的輸入?yún)?shù):SQLiteDatabasedb=databaseHelper.getWritableDatabase();Cursorcursor=db.query("person",newString[]{"personid,name,age"},"namelike?",newString[]{"%Jack%"},null,null,"personiddesc","1,2");while(cursor.moveToNext()){intpersonid=cursor.getInt(0);//獲取第一列的值,第一列的索引從0開始Stringname=cursor.getString(1);//獲取第二列的值intage=cursor.getInt(2);//獲取第三列的值}cursor.close();db.close();上面代碼用于從person表中查找name字段含有“傳智”的記錄,匹配的記錄按personid降序排序,對排序后的結果略過第一條記錄,只獲取2條記錄。query(table,columns,selection,selectionArgs,groupBy,having,orderBy,limit)方法各參數(shù)的含義:table:表名。相當于select語句from關鍵字后面的局部。如果是多表聯(lián)合查詢,可以用逗號將兩個表名分開。columns:要查詢出來的列名。相當于select語句select關鍵字后面的局部。selection:查詢條件子句,相當于select語句where關鍵字后面的局部,在條件子句允許使用占位符“?”selectionArgs:對應于selection語句中占位符的值,值在數(shù)組中的位置與占位符在語句中的位置必須一致,否那么就會有異常。groupBy:相當于select語句groupby關鍵字后面的局部having:相當于select語句having關鍵字后面的局部orderBy:相當于select語句orderby關鍵字后面的局部,如:personiddesc,ageasc;limit:指定偏移量和獲取的記錄數(shù),相當于select語句limit關鍵字后面的局部。使用SQLiteOpenHelper對數(shù)據(jù)庫進行版本管理如果應用使用到了SQLite數(shù)據(jù)庫,在用戶初次使用軟件時,需要創(chuàng)立應用使用到的數(shù)據(jù)庫表結構及添加一些初始化記錄,另外在軟件升級的時候,也需要對數(shù)據(jù)表結構進行更新。在Android系統(tǒng),為我們提供了一個名為SQLiteOpenHelper的類,該類用于對數(shù)據(jù)庫版本進行管理,該類是一個抽象類,必須繼承它才能使用。為了實現(xiàn)對數(shù)據(jù)庫版本進行管理,SQLiteOpenHelper類有兩種重要的方法,分別是onCreate(SQLiteDatabasedb)和onUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion)當調用SQLiteOpenHelper的getWritableDatabase()或者getReadableDatabase()方法獲取用于操作數(shù)據(jù)庫的SQLiteDatabase實例的時候,如果數(shù)據(jù)庫不存在,Android系統(tǒng)會自動生成一個數(shù)據(jù)庫,接著調用onCreate()方法,onCreate()方法在初次生成數(shù)據(jù)庫時才會被調用,在onCreate()方法里可以生成數(shù)據(jù)庫表結構及添加一些應用使用到的初始化數(shù)據(jù)。onUpgrade()方法在數(shù)據(jù)庫的版本發(fā)生變化時會被調用,數(shù)據(jù)庫的版本是由程序員控制的,假設數(shù)據(jù)庫現(xiàn)在的版本是1,由于業(yè)務的需要,修改了數(shù)據(jù)庫表的結構,這時候就需要升級軟件,升級軟件時希望更新用戶里的數(shù)據(jù)庫表結構,為了實現(xiàn)這一目的,可以把原來的數(shù)據(jù)庫版本設置為2(有同學問設置為3行不行?當然可以,如果你愿意,設置為100也行),并且在onUpgrade()方法里面實現(xiàn)表結構的更新。當軟件的版本升級次數(shù)比較多,這時在onUpgrade()方法里面可以根據(jù)原版號和目標版本號進行判斷,然后作出相應的表結構及數(shù)據(jù)更新。getWritableDatabase()和getReadableDatabase()方法都可以獲取一個用于操作數(shù)據(jù)庫的SQLiteDatabase實例。但getWritableDatabase()方法以讀寫方式翻開數(shù)據(jù)庫,一旦數(shù)據(jù)庫的磁盤空間滿了,數(shù)據(jù)庫就只能讀而不能寫,倘假設使用的是getWritableDatabase()方法就會出錯。getReadableDatabase()方法先以讀寫方式翻開數(shù)據(jù)庫,如果數(shù)據(jù)庫的磁盤空間滿了,就會翻開失敗,當翻開失敗后會繼續(xù)嘗試以只讀方式翻開數(shù)據(jù)庫。使用SQLiteOpenHelper對數(shù)據(jù)庫進行版本管理publicclassDatabaseHelperextendsSQLiteOpenHelper{//類沒有實例化,是不能用作父類構造器的參數(shù),必須聲明為靜態(tài)privatestaticfinalStringname="itcast";//數(shù)據(jù)庫名稱privatestaticfinalintversion=1;//數(shù)據(jù)庫版本publicDatabaseHelper(Contextcontext){//第三個參數(shù)CursorFactory指定在執(zhí)行查詢時獲得一個游標實例的工廠類,設置為null,代表使用系統(tǒng)默認的工廠類super(context,name,null,version);}@OverridepublicvoidonCreate(SQLiteDatabasedb){db.execSQL("CREATETABLEIFNOTEXISTSperson(personidintegerprimarykeyautoincrement,namevarchar(20),ageINTEGER)");}@OverridepublicvoidonUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion){db.execSQL("DROPTABLEIFEXISTSperson");onCreate(db);}}上面onUpgrade()方法在數(shù)據(jù)庫版本每次發(fā)生變化時都會把用戶上的數(shù)據(jù)庫表刪除,然后再重新創(chuàng)立。一般在實際工程中是不能這樣做的,正確的做法是在更新數(shù)據(jù)庫表結構時,還要考慮用戶存放于數(shù)據(jù)庫中的數(shù)據(jù)不會喪失。使用SQLiteOpenHelper獲取用于操作數(shù)據(jù)庫的SQLiteDatabase實例publicclassDatabaseHelperextendsSQLiteOpenHelper{privatestaticfinalStringname="itcast";//數(shù)據(jù)庫名稱privatestaticfinalintversion=1;//數(shù)據(jù)庫版本......略}publicclassHelloActivityextendsActivity{@OverridepublicvoidonCreate(BundlesavedInstanceState){......Buttonbutton=(Button)this.findViewById(R.id.button);button.setOnClickListener(newView.OnClickListener(){ publicvoidonClick(Viewv){ DatabaseHelperdatabaseHelper=newDatabaseHelper(HelloActivity.this); SQLiteDatabasedb=databaseHelper.getWritableDatabase(); db.execSQL("insertintoperson(name,age)values(?,?)",newObject[]{"傳智播客",4}); db.close(); }});}}第一次調用getWritableDatabase()或getReadableDatabase()方法后,SQLiteOpenHelper會緩存當前的SQLiteDatabase實例,SQLiteDatabase實例正常情況下會維持數(shù)據(jù)庫的翻開狀態(tài),所以在你不再需要SQLiteDatabase實例時,請及時調用close()方法釋放資源。一旦SQLiteDatabase實例被緩存,屢次調用getWritableDatabase()或getReadableDatabase()方法得到的都是同一實例。使用事務操作SQLite數(shù)據(jù)庫使用SQLiteDatabase的beginTransaction()方法可以開啟一個事務,程序執(zhí)行到endTransaction()方法時會檢查事務的標志是否為成功,如果為成功那么提交事務,否那么回滾事務。當應用需要提交事務,必須在程序執(zhí)行到endTransaction()方法之前使用setTransactionSuccessful()方法設置事務的標志為成功,如果不調用setTransactionSuccessful()方法,默認會回滾事務。使用例子如下:

SQLiteDatabasedb=....;db.beginTransaction();//開始事務try{db.execSQL("insertintoperson(name,age)values(?,?)",newObject[]{"Jack",4});db.execSQL("updatepersonsetname=?wherepersonid=?",newObject[]{"Jack",1});db.setTransactionSuccessful();//調用此方法會在執(zhí)行到endTransaction()時提交當前事務,如果不調用此方法會回滾事務}finally{db.endTransaction();//由事務的標志決定是提交事務,還是回滾事務}db.close();上面兩條SQL語句在同一個事務中執(zhí)行。ContentProvider使用ContentProvider共享數(shù)據(jù)當應用繼承ContentProvider類,并重寫該類用于提供數(shù)據(jù)和存儲數(shù)據(jù)的方法,就可以向其他應用共享其數(shù)據(jù)。雖然使用其他方法也可以對外共享數(shù)據(jù),但數(shù)據(jù)訪問方式會因數(shù)據(jù)存儲的方式而不同,如:采用文件方式對外共享數(shù)據(jù),需要進行文件操作讀寫數(shù)據(jù);采用sharedpreferences共享數(shù)據(jù),需要使用sharedpreferencesAPI讀寫數(shù)據(jù)。而使用ContentProvider共享數(shù)據(jù)的好處是統(tǒng)一了數(shù)據(jù)訪問方式。當應用需要通過ContentProvider對外共享數(shù)據(jù)時,第一步需要繼承ContentProvider并重寫下面方法:publicclassPersonContentProviderextendsContentProvider{publicbooleanonCreate()publicUriinsert(Uriuri,ContentValuesvalues)publicintdelete(Uriuri,Stringselection,String[]selectionArgs)publicintupdate(Uriuri,ContentValuesvalues,Stringselection,String[]selectionArgs)publicCursorquery(Uriuri,String[]projection,Stringselection,String[]selectionArgs,StringsortOrder)publicStringgetType(Uriuri)}第二步需要在AndroidManifest.xml使用<provider>對該ContentProvider進行配置,為了能讓其他應用找到該ContentProvider,ContentProvider采用了authorities〔主機名/域名〕對它進行唯一標識,你可以把ContentProvider看作是一個網站〔想想,網站也是提供數(shù)據(jù)者〕,authorities就是他的域名:<manifest....><applicationandroid:icon="@drawable/icon"android:label="@string/app_name"><providerandroid:name=".PersonContentProvider"android:authorities="vider.personprovider"/></application></manifest>注意:一旦應用繼承了ContentProvider類,后面我們就會把這個應用稱為ContentProvider〔內容提供者〕。Uri介紹Uri介紹Uri代表了要操作的數(shù)據(jù),Uri主要包含了兩局部信息:1》需要操作的ContentProvider,2》對ContentProvider中的什么數(shù)據(jù)進行操作,一個Uri由以下幾局部組成:ContentProvider〔內容提供者〕的scheme已經由Android所規(guī)定,scheme為:content://主機名〔或叫Authority〕用于唯一標識這個ContentProvider,外部調用者可以根據(jù)這個標識來找到它。路徑〔path〕可以用來表示我們要操作的數(shù)據(jù),路徑的構建應根據(jù)業(yè)務而定,如下:要操作person表中id為10的記錄,可以構建這樣的路徑:/person/10要操作person表中id為10的記錄的name字段,person/10/name要操作person表中的所有記錄,可以構建這樣的路徑:/person要操作xxx表中的記錄,可以構建這樣的路徑:/xxx當然要操作的數(shù)據(jù)不一定來自數(shù)據(jù)庫,也可以是文件等他存儲方式,如下:要操作xml文件中person節(jié)點下的name節(jié)點,可以構建這樣的路徑:/person/name如果要把一個字符串轉換成Uri,可以使用Uri類中的parse()方法,如下:Uriuri=Uri.parse("content://vider.personprovider/person")

UriMatcher類使用介紹因為Uri代表了要操作的數(shù)據(jù),所以我們很經常需要解析Uri,并從Uri中獲取數(shù)據(jù)。Android系統(tǒng)提供了兩個用于操作Uri的工具類,分別為UriMatcher和ContentUris。掌握它們的使用,會便于我們的開發(fā)工作。UriMatcher類用于匹配Uri,它的用法如下:首先第一步把你需要匹配Uri路徑全部給注冊上,如下://常量UriMatcher.NO_MATCH表示不匹配任何路徑的返回碼UriMatchersMatcher=newUriMatcher(UriMatcher.NO_MATCH);//如果match()方法匹配路徑,返回匹配碼為1sMatcher.addURI(“vider.personprovider”,“person”,1);//添加需要匹配uri,如果匹配就會返回匹配碼//如果match()方法匹配路徑,返回匹配碼為2sMatcher.addURI(“vider.personprovider”,“person/#”,2);//#號為通配符switch(sMatcher.match(Uri.parse("content://vider.personprovider/person/10"))){case1break;case2break;default://不匹配

break;}注冊完需要匹配的Uri后,就可以使用sMatcher.match(uri)方法對輸入的Uri進行匹配,如果匹配就返回匹配碼,匹配碼是調用addURI()方法傳入的第三個參數(shù),假設匹配路徑,返回的匹配碼為1ContentUris類使用介紹ContentUris類用于獲取Uri路徑后面的ID局部,它有兩個比較實用的方法:withAppendedId(uri,id)用于為路徑加上ID局部:Uriuri=Uri.parse("content://vider.personprovider/person")UriresultUri=ContentUris.withAppendedId(uri,10);//生成后的Uri為:parseId(uri)方法用于從路徑中獲取ID局部:Uriuri=Uri.parse("content://vider.personprovider/person/10")longpersonid=ContentUris.parseId(uri);//獲取的結果為:10使用ContentProvider共享數(shù)據(jù)ContentProvider類主要方法的作用:publicbooleanonCreate()該方法在ContentProvider創(chuàng)立后就會被調用,Android在系統(tǒng)啟動時就會創(chuàng)立ContentProvider。publicUriinsert(Uriuri,ContentValuesvalues)該方法用于供外部應用往ContentProvider添加數(shù)據(jù)。publicintdelete(Uriuri,Stringselection,String[]selectionArgs)該方法用于供外部應用從ContentProvider刪除數(shù)據(jù)。publicintupdate(Uriuri,ContentValuesvalues,Stringselection,String[]selectionArgs)該方法用于供外部應用更新ContentProvider中的數(shù)據(jù)。publicCursorquery(Uriuri,String[]projection,Stringselection,String[]selectionArgs,StringsortOrder)該方法用于供外部應用從ContentProvider中獲取數(shù)據(jù)。publicStringgetType(Uriuri)該方法用于返回當前Url所代表數(shù)據(jù)的MIME類型。如果操作的數(shù)據(jù)屬于集合類型,那么MIME類型字符串應該以開頭,例如:要得到所有person記錄的Uri為,那么返回的MIME類型字符串應該為:“vnd.android.cursor.dir/person”。如果要操作的數(shù)據(jù)屬于單一數(shù)據(jù),那么MIME類型字符串應該以開頭,例如:得到id為10的person記錄,Uri為,那么返回的MIME類型字符串應該為:“vnd.android.cursor.item/person”。使用ContentResolver操作ContentProvider中的數(shù)據(jù)當外部應用需要對ContentProvider中的數(shù)據(jù)進行添加、刪除、修改和查詢操作時,可以使用ContentResolver類來完成,要獲取ContentResolver對象,可以使用Activity提供的getContentResolver()方法。ContentResolver類提供了與ContentProvider類相同簽名的四個方法:publicUriinsert(Uriuri,ContentValuesvalues)該方法用于往ContentProvider添加數(shù)據(jù)。publicintdelete(Uriuri,Stringselection,String[]selectionArgs)該方法用于從ContentProvider刪除數(shù)據(jù)。publicintupdate(Uriuri,ContentValuesvalues,Stringselection,String[]selectionArgs)該方法用于更新ContentProvider中的數(shù)據(jù)。publicCursorquery(Uriuri,String[]projection,Stringselection,String[]selectionArgs,StringsortOrder)該方法用于從ContentProvider中獲取數(shù)據(jù)。這些方法的第一個參數(shù)為Uri,代表要操作的是哪個ContentProvider和對其中的什么數(shù)據(jù)進行操作,假設給定的是:Uri.parse(“content://vider.personprovider/person/10”),那么將會對主機名為的ContentProvider進行操作,操作的數(shù)據(jù)為person表中id為10的記錄。使用ContentResolver操作ContentProvider中的數(shù)據(jù)使用ContentResolver對ContentProvider中的數(shù)據(jù)進行添加、刪除、修改和查詢操作:ContentResolverresolver=getContentResolver();Uriuri=Uri.parse("content://vider.personprovider/person");//添加一條記錄ContentValuesvalues=newContentValues();values.put("name","itcast");values.put("age",25);resolver.insert(uri,values); //獲取person表中所有記錄Cursorcursor=resolver.query(uri,null,null,null,"personiddesc");while(cursor.moveToNext()){ Log.i("ContentTest","personid="+cursor.getInt(0)+",name="+cursor.getString(1));}//把id為1的記錄的name字段值更改新為limingContentValuesupdateValues=newContentValues();updateValues.put("name","liming");UriupdateIdUri=ContentUris.withAppendedId(uri,2);resolver.update(updateIdUri,updateValues,null,null);//刪除id為2的記錄UrideleteIdUri=ContentUris.withAppendedId(uri,2);resolver.delete(deleteIdUri,null,null);為應用添加新的Activity第一步:新建一個繼承Activity的類,如:NewActivitypublicclassNewActivityextendsActivity{@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState); //這里可以使用setContentView(R.layout.xxx)顯示某個視圖....}}第二步:需要在功能清單AndroidManifest.xml文件中添加進上面Activity配置代碼(紅色局部):<manifestxmlns:android="://schemas.android/apk/res/android"package="cn.itcast.action"android:versionCode="1"android:versionName="1.0"><applicationandroid:icon="@drawable/icon"android:label="@string/app_name">..... <activityandroid:name=".NewActivity"android:label="新activity的頁面標題"/></application>...</manifest>android:name屬性值的前面加了一個點表示NewActivity是當前包下的類,如果類在應用的當前包下,可以省略點符號,如果類在應用的子包下必須加點,如:NewActivity類在包下可以這樣寫:<activityandroid:name=“.user.NewActivity“/>翻開新的Activity,不傳遞參數(shù)在一個Activity中可以使用系統(tǒng)提供的startActivity(Intentintent)方法翻開新的Activity,在翻開新的Activity前,你可以決定是否為新的Activity傳遞參數(shù):第一種:翻開新的Activity,不傳遞參數(shù)publicclassMainActivityextendsActivity{@OverrideprotectedvoidonCreate(BundlesavedInstanceState){ ....... Buttonbutton=(Button)this.findViewById(R.id.button);button.setOnClickListener(newView.OnClickListener(){//點擊該按鈕會翻開一個新的Activity publicvoidonClick(Viewv){//新建一個顯式意圖,第一個參數(shù)為當前Activity類對象,第二個參數(shù)為你要翻開的Activity類 startActivity(newIntent(MainActivity.this,NewActivity.class)); }});}}翻開新的Activity,并傳遞假設干個參數(shù)給它第二種:翻開新的Activity,并傳遞假設干個參數(shù)給它:publicclassMainActivityextendsActivity{@OverrideprotectedvoidonCreate(BundlesavedInstanceState){ ....... button.setOnClickListener(newView.OnClickListener(){//點擊該按鈕會翻開一個新的Activity publicvoidonClick(Viewv){ Intentintent=newIntent(MainActivity.this,NewActivity.class)Bundlebundle=newBundle();//該類用作攜帶數(shù)據(jù)bundle.putString("name","傳智播客");bundle.putInt("age",4);intent.putExtras(bundle);//附帶上額外的數(shù)據(jù)startActivity(intent); }});}}在新的Activity中接收前面Activity傳遞過來的參數(shù):publicclassNewActivityextendsActivity{@OverrideprotectedvoidonCreate(BundlesavedInstanceState){ ........ Bundlebundle=this.getIntent().getExtras(); Stringname=bundle.getString("name"); intage=bundle.getInt("age");}}Bundle類的作用Bundle類用作攜帶數(shù)據(jù),它類似于Map,用于存放key-value名值對形式的值。相對于Map,它提供了各種常用類型的putXxx()/getXxx()方法,如:putString()/getString()和putInt()/getInt(),putXxx()用于往Bundle對象放入數(shù)據(jù),getXxx()方法用于從Bundle對象里獲取數(shù)據(jù)。Bundle的內部實際上是使用了HashMap<String,Object>類型的變量來存放putXxx()方法放入的值:publicfinalclassBundleimplementsParcelable,Cloneable{......

Map<String,Object>mMap;publicBundle(){mMap=newHashMap<String,Object>();......}publicvoidputString(Stringkey,Stringvalue){mMap.put(key,value);}publicStringgetString(Stringkey){

Objecto=mMap.get(key);return(String)o;

........//類型轉換失敗后會返回null,這里省略了類型轉換失敗后的處理代碼}}在調用Bundle對象的getXxx()方法時,方法內部會從該變量中獲取數(shù)據(jù),然后對數(shù)據(jù)進行類型轉換,轉換成什么類型由方法的Xxx決定,getXxx()方法會把轉換后的值返回。為Intent附加數(shù)據(jù)的兩種寫法第一種寫法,用于批量添加數(shù)據(jù)到Intent:Intentintent=newIntent();Bundlebundle=newBundle();//該類用作攜帶數(shù)據(jù)bundle.putString("name","傳智播客");intent.putExtras(bundle);//為意圖追加額外的數(shù)據(jù),意圖原來已經具有的數(shù)據(jù)不會喪失,但key同名的數(shù)據(jù)會被替換第二種寫法:這種寫法的作用等價于上面的寫法,只不過這種寫法是把數(shù)據(jù)一個個地添加進Intent,這種寫法使用起來比較方便,而且只需要編寫少量的代碼。Intentintent=newIntent();intent.putExtra("name","傳智播客");Intent提供了各種常用類型重載后的putExtra()方法,如:putExtra(Stringname,Stringvalue)、putExtra(Stringname,longvalue),在putExtra()方法內部會判斷當前Intent對象內部是否已經存在一個Bundle對象,如果不存在就會新建Bundle對象,以后調用putExtra()方法傳入的值都會存放于該Bundle對象,下面是Intent的putExtra(Stringname,Stringvalue)方法代碼片斷:publicclassIntentimplementsParcelable{privateBundlemExtras;publicIntentputExtra(Stringname,Stringvalue){if(mExtras==null){mExtras=newBundle();}mExtras.putString(name,value);returnthis;}得到新翻開Activity關閉后返回的數(shù)據(jù)如果你想在Activity中得到新翻開Activity關閉后返回的數(shù)據(jù),你需要使用系統(tǒng)提供的startActivityForResult(Intentintent,intrequestCode)方法翻開新的Activity,新的Activity關閉后會向前面的Activity傳回數(shù)據(jù),為了得到傳回的數(shù)據(jù),你必須在前面的Activity中重寫onActivityResult(intrequestCode,intresultCode,Intentdata)方法:publicclassMainActivityextendsActivity{@OverrideprotectedvoidonCreate(BundlesavedInstanceState){ ....... Buttonbutton=(Button)this.findViewById(R.id.button);button.setOnClickListener(newView.OnClickListener(){//點擊該按鈕會翻開一個新的Activity publicvoidonClick(Viewv){ //第二個參數(shù)為請求碼,可以根據(jù)業(yè)務需求自己編號 startActivityForResult(newIntent(MainActivity.this,NewActivity.class),1); }});}//第一個參數(shù)為請求碼,即調用startActivityForResult()傳遞過去的值//第二個參數(shù)為結果碼,結果碼用于標識返回數(shù)據(jù)來自哪個新Activity@OverrideprotectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){ Stringresult=data.getExtras().getString(“result”));//得到新Activity關閉后返回的數(shù)據(jù)}}當新Activity關閉后,新Activity返回的數(shù)據(jù)通過Intent進行傳遞,android平臺會調用前面Activity的onActivityResult()方法,把存放了返回數(shù)據(jù)的Intent作為第三個輸入?yún)?shù)傳入,在onActivityResult()方法中使用第三個輸入?yún)?shù)可以取出新Activity返回的數(shù)據(jù)。請求碼的作用使用startActivityForResult(Intentintent,intrequestCode)方法翻開新的Activity,我們需要為startActivityForResult()方法傳入一個請求碼(第二個參數(shù))。請求碼的值是根據(jù)業(yè)務需要由自已設定,用于標識請求來源。例如:一個Activity有兩個按鈕,點擊這兩個按鈕都會翻開同一個Activity,不管是那個按鈕翻開新Activity,當這個新Activity關閉后,系統(tǒng)都會調用前面Activity的onActivityResult(intrequestCode,intresultCode,Intentdata)方法。在onActivityResult()方法如果需要知道新Activity是由那個按鈕翻開的,并且要做出相應的業(yè)務處理,這時可以這樣做:@OverridepublicvoidonCreate(BundlesavedInstanceState){....button1.setOnClickListener(newView.OnClickListener(){ publicvoidonClick(Viewv){ startActivityForResult(newIntent(MainActivity.this,NewActivity.class),1); }});button2.setOnClickListener(newView.OnClickListener(){ publicvoidonClick(Viewv){ startActivityForResult(newIntent(MainActivity.this,NewActivity.class),2); }});@OverrideprotectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){switch(requestCode){case1://來自按鈕1的請求,作相應業(yè)務處理case2: //來自按鈕2的請求,作相應業(yè)務處理}}}結果碼的作用在一個Activity中,可能會使用startActivityForResult()方法翻開多個不同的Activity處理不同的業(yè)務,當這些新Activity關閉后,系統(tǒng)都會調用前面Activity的onActivityResult(intrequestCode,intresultCode,Intentdata)方法。為了知道返回的數(shù)據(jù)來自于哪個新Activity,在onActivityResult()方法中可以這樣做(ResultActivity和NewActivity為要翻開的新Activity):publicclassResultActivityextendsActivity{.....ResultActivity.this.setResult(1,intent);ResultActivity.this.finish

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論