版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
Android移動存儲解決方案目標學員:學習目標:
課程時長:Android中級開發(fā)者SharedPreferencesContentProvider文件數(shù)據(jù)庫4學時,180分鐘1SharedPreferences2ContentProvider4數(shù)據(jù)庫3文件課程目錄理解Android應用中重要的四種數(shù)據(jù)存儲機制原理能夠熟練的混合使用四種存儲技術(shù)ContentProvider數(shù)據(jù)存儲內(nèi)部及外部文件的讀取Sqlite數(shù)據(jù)庫的使用1SharedPreferences2ContentProvider4數(shù)據(jù)庫3文件課程目錄SharedPreferencesSharedPreferences的介紹使用SharedPreferencesSharedPreference介紹軟件配置參數(shù)的保存,windows采用ini文件保存,j2se應用采用properties屬性文件保存,android應用可以采用SharedPreferencesSharedPreferences是一種輕量級的鍵值存儲方式,其存儲的數(shù)據(jù)必須是基本數(shù)據(jù)類型。SharedPreferences存儲的數(shù)據(jù)以XML的形式存在,存儲在/data/data/包名/shared_prefs目錄下。下面是一個Preference文件的示例。 <?xmlversion='1.0'encoding='utf-8'standalone='yes'?> <map> <stringname="gender">男性</string> <stringname="name">jadde</string> </map>相關(guān)介紹-SharedPreferences接口通過Context提供的getSharedPreferences(名字,模式)方法來獲取SharedPreferences實例,模式包括以下幾種:Context.MODE_PRIVATE:Context.MODE_APPEND:Context.MODE_WORLD_READABLE:Context.MODE_WORLD_WRITABLE:例如:SharedPreferencespres=MainActivity.this.getSharedPreferences("soft",Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE);相關(guān)介紹-Editor對象SharedPreferences接口沒有提供寫入數(shù)據(jù)的能力,要調(diào)用SharedPreferences的edit()來獲取它所對應的Editor對象。它有一系列操作數(shù)據(jù)的方法.putString(Stringname,Stringvalue):存儲鍵值,
getString(Stringname,Stringvalue):獲取鍵值,
Clear():清除鍵值。
Commit():執(zhí)行相關(guān)操作之后,調(diào)用此方法確認數(shù)據(jù)的改變。例如:Editoreditor=sharedPreferences.edit();editor.putString(“name”,”zy”);editor.putInt(“age”,44);mit();案例一:讀取和寫入數(shù)據(jù)
finalSharedPreferencessp=MainActivity.this.getSharedPreferences("ma",MainActivity.MODE_PRIVATE);
finalEditoreditor=sp.edit();write=(Button)this.findViewById(R.id.write);read=(Button)this.findViewById(R.id.read);result=(TextView)this.findViewById(R.id.result);write.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(Viewv){Dated=newDate();DateFormatdf=newSimpleDateFormat("yyyy年MM月dd日");editor.putString("d",df.format(d));editor.putInt("randnum",(int)(Math.random()*100));mit();}});read.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(Viewv){Stringd=sp.getString("d","");intrandnum=sp.getInt("randnum",0);result.setText("時間:"+d+"隨機數(shù)為:"+randnum);}});案例二:記錄程序運行次數(shù)案例三:讀寫其它應用SharedPreferences前提:創(chuàng)建的SharedPreferences文件的訪問權(quán)限設(shè)定為:MODE_WORLD_READABLE或MODE_WORLD_WRITABLE步驟:1.創(chuàng)建其他程序?qū)腃ontext2.調(diào)用其它程序的SharedPreferences.案例:Contextcontext=MainActivity.this.createPackageContext("com.icss.test_sharedPreferences.ui",Context.CONTEXT_INCLUDE_CODE);SharedPreferencessp=context.getSharedPreferences("ma",Context.MODE_WORLD_WRITEABLE);1SharedPreferences2文件4數(shù)據(jù)庫3課程目錄ContentProvider文件文件存儲概述內(nèi)部存儲外部存儲讀取資源文件XML文件解析之SAX解析,PULL解析.文件存儲概述從存儲位置上區(qū)分,Android的文件可以存儲在手機的內(nèi)存或者外部的存儲卡上。Android平臺支持完整的java.io包,文件操作與PC上的Java開發(fā)差異不大。內(nèi)部存儲默認情況下,在/data/data/<包名>/files/目錄下創(chuàng)建文件,且生成一個文件輸出流(FileOutputStream)對象。Context提供了openFileOutput(Stringname,intmode),name表示文件名,參數(shù)mode表示文件打開或者創(chuàng)建的方式。
MODE_PRIVATE:表示該文件只能被本應用訪問; MODE_APPEND:表示新的內(nèi)容會添加在原文件內(nèi)容的后面; MODE_WORLD_WRITABLE:表示該文件能被所有應用寫入; MODE_WORLD_READABLE:表示該文件能被所有應用讀??;存儲到data目錄默認情況下,文件被存儲在應用程序所在目錄,其他應用程序無法訪問。
//將文件存儲至默認文件夾privatevoidsaveToDefault(byte[]buf)throwsIOException{ ileOutputStreamfos_1=openFileOutput("test_1.txt", Context.MODE_APPEND); os_1.write(buf); os_1.close();} 如果希望將文件存儲在data目錄下的子目錄,可以使用File類。privatevoidsaveToDirectory(byte[]buf)throwsIOException{FiletextFile_2=newFile( "/data/data/com.A/test_2.txt"); FileOutputStreamfos_2=newFileOutputStream(textFile_2); fos_2.write(buf); fos_2.close();}讀取內(nèi)部文件調(diào)用Context類的openFileInput()方法,返回FileInputStream。調(diào)用read()方法從文件中讀取數(shù)據(jù)操作完成后,調(diào)用close()方法關(guān)閉輸入流。FileInputStreamfis_1=openFileInput("test_1.txt");fis_1.read(buf);fis_1.close(); 案例一:內(nèi)部文件讀寫功能:在主界面輸入文本后能存入到手機中,也能讀取文本顯示到界面上架構(gòu):MVC技術(shù)點:1.測試框架的使用2.文件流的操作3.手機文件操作案例一:內(nèi)部文件讀寫步驟一:配置junit框架
<!--加載測試框架庫文件--><uses-libraryandroid:name="android.test.runner"/>
<!--將當前應用放入到測試中運行--><instrumentationandroid:name="android.test.InstrumentationTestRunner"android:targetPackage="com.icss.test_innerfilereadwrite"android:label="test"/>
步驟二:完成業(yè)務類FileService
publicstaticvoidsave(OutputStreamoutputStream,byte[]content){ outputStream.write(content); outputStream.close();}
publicstaticbyte[]read(InputStreaminputStream){ byte[]result=null; ByteArrayOutputStreamoutputStream=newByteArrayOutputStream(); byte[]buffer=newbyte[1024]; intlen=-1; while((len=inputStream.read(buffer))!=-1){ outputStream.write(buffer,0,len); } result=outputStream.toByteArray(); inputStream.close(); outputStream.close(); returnresult;}
案例一:內(nèi)部文件讀寫步驟三:junit框架測試
publicclassTestFileextendsAndroidTestCase{ publicvoidtestSave()throwsIOException{ //this指代的是當前測試類的對象,通過它取到這個應用的上下文對象 FileOutputStreamoutputStream=this.getContext().openFileOutput ("icss.txt",Context.MODE_APPEND); FileService.save(outputStream,"abc中國".getBytes()); } publicvoidtestRead()throwsIOException{ FileInputStreaminputStream=this.getContext().openFileInput("icss.txt"); byte[]result=FileService.read(inputStream); Log.i("read",newString(result,"utf-8")); }}步驟四:界面開發(fā)
FileOutputStreamoutputStream=MainActivity.this.openFileOutput(fn,Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE);
通過修改上面的權(quán)限,可以控制是否讓外部程序讀取本應用中的文件.緩存文件不希望持久性存儲文件,只是為了緩存。getCacheDir()可以返回File對象,代表臨時的緩存文件。當內(nèi)存不足的時候,系統(tǒng)可以選擇刪除這些緩存文件。緩存的空間不應該過大,應用程序應該自己維護這些文件。當應用程序被卸載,緩存文件也被刪除。外部存儲外部存儲是指將文件存儲在存儲卡或者內(nèi)置的存儲設(shè)備上。通常使用File類操作外部存儲的文件。
在參數(shù)path指定的位置創(chuàng)建文件。
參數(shù)path表示包含絕對路徑的文件名,且該路徑應在目錄
“/data/data/<包名>/”或SD卡可寫目錄中。
使用FileOutputStream(Filefile)方法可以為創(chuàng)建的文件生成一
個文件輸出流對象。案例二:將文件保存到SDCARD中在模擬器中使用SDCARD,你需要先創(chuàng)建一張SDCARD卡,創(chuàng)建SDCARD可以在Eclipse創(chuàng)建模擬器時隨同創(chuàng)建,也可以使用DOS命令創(chuàng)建,如下:
在DOS窗口中進入androidSDK安裝路徑的tools目錄,輸入以下命令:Mksdcard2048mD:\androidtool\sdcard.img在程序中訪問SDCARD,你需要申請訪問SDCARDr權(quán)限.在androidManifest.xml中加入創(chuàng)建與刪除文件權(quán)限:<uses-permissionandroid:name=”android.permission.MOUNT_UNMOUNT_FILESYSTEMS”/><uses-permissionandroid:name=”android.permission.WRITE_EXTERNAL_STORAGE”/>//判斷是否存在SDCardIf(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){Filefile=newFile(Environment.getExternalStorageDirector(),filename); FileOutputStreamoutStream=newFileOutputStream(file); fileService.save(outStream,content); }讀資源文件(一)對于本工程的res/raw目錄下的資源文件,會在R清單類中生成一個索引項,通過Resources類的openRawResource方法,并得到輸入流(InputStream)。InputStreamis=getResources().openRawResource(R.raw.test);案例:播放res/raw下的音樂finalMediaPlayermp=MediaPlayer.create(MainActivity.this,R.raw.a);Buttonb=(Button)this.findViewById(R.id.start);b.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(Viewv){mp.start();}});讀資源文件(二)對于本工程的assets目錄下的資源文件,使用AssetManager的open方法,并得到輸入流(InputStream)。InputStreamis=AssetManager.open(Stringname,intaccessMode);案例:播放Assets下的音樂AssetManageram=MainActivity.this.getAssets();AssetFileDescriptorafd=am.openFd("a.mp3");Buttonb=(Button)this.findViewById(R.id.start);b.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(Viewv){ mp=newMediaPlayer(); mp.setDataSource(afd.getFileDescriptor()); mp.prepare(); mp.start();}});本案例演示向默認目錄、指定目錄、SD卡中存儲數(shù)據(jù),以及從資源文件中獲得數(shù)據(jù)的方法,并介紹了文件不同的打開方式對存儲結(jié)果的影響。下面是此案例運行的結(jié)果:XML解析在android平臺上可以使用SimpleAPIfroXML(sax),DocumentobjectModel(DOM)和android附帶的pull解析器解析XML文件.(一)Sax是一個解析速度快并且占用內(nèi)存較少的xml解析器,適合用于移動設(shè)備。SAX采用事件驅(qū)動機制,即它并不需要解析完整個文檔,在按內(nèi)容順序解析文檔的過程中,SAX會判斷當前讀到的字符是否為合法XML語法中的某部分,如果符合就會觸發(fā)事件。所謂事件,其實就是一些回調(diào)(callback)方法,這些方法(事件)定義在ContentHandler接口。下面是一些ContentHandler接口的常用方法:startDocument():當遇到文檔的開頭的時候調(diào)用這個方法,做預處理工作endDocument():當文檔結(jié)束時調(diào)用此方法,做善后工作startElement(StringnamespaceURI,StringlocalName,StringqName,Attributesatts):當讀到一個開始標簽時,會觸發(fā)這個方法。namespaceURI就是命名空間,localName是不帶命名空間前綴的標簽名,qName是帶命名空間前綴的標簽名。通過atts可以得到所有的屬性名和相應的值。注意:SAX中一個重要的特點就是它的流式處理,當遇到一個標簽的時候,它并不會記錄下以前所碰到的標簽,也就是說,在startElement()方法中,所有你所知道的信息,就是標簽的名字和屬性,至于標簽所的嵌套的結(jié)構(gòu),上層標簽的名字,是否有子元素等其它的與結(jié)構(gòu)相關(guān)的信息,都是不得而知的,都需要你的程序來完成。endElement(Stringuri,StringlocalName,Stringname):結(jié)束標簽時調(diào)用characters(char[]ch,intstart,intlength):用來處理在xml文件中讀到的內(nèi)容,第一個參數(shù)用于存放文件的內(nèi)容,后面兩個參數(shù)是讀到的字符串在這個數(shù)組中的起始位置和長度,使用newString(ch,start,length)就可以獲取內(nèi)容.
XML解析-SAX解析模擬:
標簽及內(nèi)容
觸發(fā)的事件{文檔開始} startDocument()<students>startElement(“”,”persons”,null,”{Attributes}”)“\n\t”characters(“<students>…</students>”,”12”,’2”);<person>startElement(“”,”person”,null,”{Attributes}”)……
只要為SAX提供實現(xiàn)ContentHandler接口的類,那么這個類就可以得到通知事件(實際上是SAX調(diào)用了該類中的回調(diào)方法).因為ContentHandler是一個接口,在使用的時候可能會有些不方便,因此,SAX還為其制定了一個HELPer類:DefaultHandler,它實現(xiàn)了這個接口,但是其所有的方法體都為空,在實現(xiàn)的時候,你只需要繼承這個類。然后重載相應的方法即可。案例-xml文件的SAX解析步驟一:寫一個類繼承自DefaultHandler類,并重寫其中的方法步驟二:寫一個業(yè)務類來獲取解析器業(yè)務類的核心代碼:
public
staticList<Student>readXML(InputStreaminputStream)
throwsException{ //設(shè)置解析器的相關(guān)特性,開啟命名空間特性 //saxParser.setProperty("/sax/features/namespaces", //true); XMLContentHandlerhandler; SAXParserFactoryspf=SAXParserFactory.newInstance(); SAXParsersaxParser=spf.newSAXParser(); handler=newXMLContentHandler(); saxParser.parse(inputStream,handler); inputStream.close();
returnhandler.getStudents(); }案例-xml文件的SAX解析步驟三:界面的調(diào)用
分三種情況:1.訪問類路徑下的xml文件:InputStreaminputStream=MainActivity.this.getClassLoader().getResourceAsStream("students.xml");2.訪問手機文件:
InputStreaminputStream=MainActivity.this.openFileInput("students.xml");3.訪問SDCard上文件:
<uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/><uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){Filef=newFile(Environment.getExternalStorageDirectory(),"students.xml");InputStreaminputStream=newFileInputStream(f);
案例-XML文件的PULL解析Pull解析和Sax解析很相似,都是輕量級的解析,在Android的內(nèi)核中已經(jīng)嵌入了Pull,所以我們不需要再添加第三方j(luò)ar包來支持Pull。Pull解析和Sax解析不一樣的地方有(1)pull讀取xml文件后觸發(fā)相應的事件調(diào)用方法返回的是數(shù)字(2)pull可以在程序中控制想解析到哪里就可以停止解析。Android內(nèi)置了PULL解析器。PULL解析器的運行原理與SAX類似。它提供類似事件,如開如元素和結(jié)束元素事件,使用parser.next()可以進入下一個元素并觸發(fā)相應的事件。事件將作為數(shù)值代碼被發(fā)送,因此可以使用一個switch對感興趣的事件進行處理。當元素開如解析時,調(diào)用parser.nextText()方法可以獲取下一個Text類型元素的值.Pull解析器的源碼及文檔網(wǎng)站:案例-XML文件的PULL保存publicstaticvoidsaveXmlByPull(List<Student>list,Writerwriter)throwsIllegalArgumentException,IllegalStateException,IOException{XmlSerializerserializer=Xml.newSerializer();serializer.setOutput(writer);serializer.startDocument("utf-8",true);serializer.startTag(null,"students");for(Students:list){serializer.startTag(null,"student");serializer.attribute(null,"id",""+s.getId());serializer.startTag(null,"name");serializer.text(s.getName());serializer.endTag(null,"name");serializer.startTag(null,"age");serializer.text(s.getAge()+"");serializer.endTag(null,"age");serializer.endTag(null,"student");}serializer.endTag(null,"students");serializer.endDocument();serializer.flush();writer.flush();}案例-XML文件的PULL保存1.本地文件寫入:FileOutputStreamoutputStream=MainActivity.this.openFileOutput("s.xml",MODE_WORLD_WRITEABLE);OutputStreamWriterwriter=newOutputStreamWriter(outputStream);StudentBiz.saveXmlByPull(list,writer);2.SDCARD文件寫入:
權(quán)限:<uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/><uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){Filef=newFile(Environment.getExternalStorageDirectory(),"s.xml");FileOutputStreamoutputStream=newFileOutputStream(f);OutputStreamWriterwriter=newOutputStreamWriter(outputStream);StudentBiz.saveXmlByPull(list,writer);}
PULL解析-作業(yè)要解析的網(wǎng)絡(luò)文件:/iphone/xml/bj.xml要點提示:1.要訪問網(wǎng)絡(luò),權(quán)限:<uses-permissionandroid:name="android.permission.INTERNET"></uses-permission>2.網(wǎng)絡(luò)訪問:
xmlPullParser.setInput(url.openConnection().getInputStream(),"UTF-8");3.分析Xml文件,找出它的格式,并分析出有用的數(shù)據(jù).
源代碼1SharedPreferences2ContentProvider4文件3數(shù)據(jù)庫課程目錄數(shù)據(jù)庫數(shù)據(jù)庫概述創(chuàng)建數(shù)據(jù)庫操作數(shù)據(jù)SQLite數(shù)據(jù)庫介紹Android平臺內(nèi)置了對SQLite數(shù)據(jù)庫,它是輕量級的嵌入式數(shù)據(jù)庫。對于數(shù)據(jù)結(jié)構(gòu)較為復雜的關(guān)系型數(shù)據(jù),使用SQLite存儲將非常高效。應用程序創(chuàng)建的數(shù)據(jù)庫文件存儲在/data/data/包名/database目錄下,應用程序之間不能相互訪問。SQLite在底層就是一個文件.數(shù)據(jù)類型:NULL,Integer,real,text,blob.創(chuàng)建數(shù)據(jù)庫使用下面的方法可以創(chuàng)建一個SQLite數(shù)據(jù)庫Context.openOrCreateDatabase(Stringname,intmode,CursorFactoryfactory)name代表數(shù)據(jù)庫的名稱。mode代表創(chuàng)建數(shù)據(jù)庫的模式,包括MODE_PRIVATEMODE_WORLD_READABLE、MODE_WORLD_WRITEABLE。用于查詢構(gòu)造Cursor子類的對象,通常設(shè)置為null。例:Db=SQLiteDatabase.openOrCreateDatabase(“/mnt/db/temp.db3”,null);Sql=“createtablestudent(_idintegerprimarykey,namevarchar(50),passwordvarchar(50)):Db.execSQL(sql);//注意:最好將主鍵列的列名設(shè)為_id,以便與后面的適配器整合使用SQLiteDatebase的常用方法execSQL(String,sql,Object[]bindArgs):execSQL(Stringsql):CursorrawQuery(Stringsql,String[]selectionArgs):beginTransaction():開始事務endTransaction():結(jié)束事務setTransactionSuccessful();設(shè)置事務成功標志查詢方法返回的是一個Cursor對象,有以下方法來訪問游標:Move(intoffset):moveToFirst():moveToLast():moveToNext():moveToPosition():moveToPrevious():getXXX():獲取該行數(shù)據(jù)指定列的值.案例一要求:添加兩行數(shù)據(jù)后,查詢所有的數(shù)據(jù),返回Cursor對象,綁定到SimpleCursorAdapter上,并顯示在ListView中.一。保存的方法
protectedvoidsave(SQLiteDatabasedb2,Stringtstr,Stringcstr){db2.beginTransaction();try{db2.execSQL("insertintosongsvalues(null,?,?)",newString[]{tstr,cstr});db2.setTransactionSuccessful();}catch(SQLExceptione){e.printStackTrace();}db2.endTransaction();}二.顯示的方法protectedvoidshowList(Cursorc){SimpleCursorAdapteradapter=newSimpleCursorAdapter(MainActivity.this,R.layout.list_item,c,newString[]{"title","content"},newint[]{R.id.titleshow,R.id.contentshow});result.setAdapter(adapter);}三.事件調(diào)用//取出數(shù)據(jù)庫db=SQLiteDatabase.openOrCreateDatabase(this.getFilesDir()+"/my.db3",null);save.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(Viewv){Stringtstr=title.getText().toString();Stringcstr=content.getText().toString();try{save(db,tstr,cstr);Cursorc=db.rawQuery("select*fromsongs",null);showList(c);}catch(Exceptione){//當?shù)谝淮卧L問的時候,創(chuàng)建表db.execSQL("createtablesongs(_idintegerprimarykeyautoincrement,title,content)");save(db,tstr,cstr);Cursorc=db.rawQuery("select*fromsongs",null);showList(c);}}});使用SQLiteOpenHelper在Android系統(tǒng)中,提供了一個名為SQLiteOpenHelper的類,對數(shù)據(jù)庫版本進行管理,它是一個抽象類,它有兩個重載方法:onCreate(SQLiteDatabasedb)和onUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion)當調(diào)用SQLiteOpenHelper的getWritableDatabase()或者getReadableDatabase()方法獲取用于操作數(shù)據(jù)庫的SQLiteDatabase實例的時候,如果數(shù)據(jù)庫不存在,android系統(tǒng)支自動生成一個數(shù)據(jù)庫,接著調(diào)用onCreate()方法,onCreate()方法在初次生成數(shù)據(jù)庫時才會被調(diào)用,在onCreate()方法里可以生成數(shù)據(jù)庫使的結(jié)構(gòu)及添加一些應用使用到的初始化數(shù)據(jù)。onUpgrade()方法在數(shù)據(jù)庫表的版本發(fā)生變化時會被調(diào)用,數(shù)據(jù)庫的版本是由程序員控制,假設(shè)數(shù)據(jù)庫現(xiàn)在的版本是1,由于業(yè)務的需要,修改了數(shù)據(jù)庫表的結(jié)構(gòu),這時候就需要升級軟件,升級軟件希望更新用戶手機里的數(shù)據(jù)庫表結(jié)構(gòu),這樣就可以把原來數(shù)據(jù)庫版本設(shè)置為2,并且在onUpgrade()方法里面實現(xiàn)結(jié)構(gòu)的更新,當軟件的版本升級次數(shù)比較多,這時在onUpgrade())方法里面可以根據(jù)原版本號和目標版本號進行判斷,然后作出相應的表結(jié)構(gòu)及數(shù)據(jù)更新.getWritableDatabase()和getReadableDatabase()方法都是可以獲取一個用于操作數(shù)據(jù)庫的SQLiteDatabase實例,但getWritable()方法以讀寫方式打開數(shù)據(jù)庫,一旦數(shù)據(jù)庫空間滿了,db就只能讀需不能寫,若使用的是getWritableDataqbase())衣服就會出錯,getReadableDatabase()方法先以讀寫方式打開數(shù)據(jù)庫,如空間滿了,就會打開失敗,當打開失敗后可以只讀方式打開使用SQLiteOpenHelper使用SQLiteOpenHelper創(chuàng)建數(shù)據(jù)庫不會重復執(zhí)行數(shù)據(jù)庫的初始化操作。不需要查詢數(shù)據(jù)庫是否存在,執(zhí)行效率更高。SQLiteOpenHelper是一個抽象類,需要實現(xiàn)如下方法:onCreate(SQLiteDatabasedb)onUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion)調(diào)用getWritableDatabase()可以獲得可寫的SQLiteDatabase對象。調(diào)用getReadableDatabase()可以獲得一個只讀的SQLiteDatabase對象。案例:采用SQLiteOpenHelper封裝(一)DataBaseOpenHelper類:用于創(chuàng)建和修改數(shù)據(jù)庫publicclassDataBaseOpenHelperextendsSQLiteOpenHelper{privatestaticfinalStringDBNAME="persondb";privatestaticfinalintVERSION=1;publicDataBaseOpenHelper(Contextcontext,Stringname,CursorFactoryfactory,intversion){super(context,name,null,version);}publicDataBaseOpenHelper(Contextcontext){this(context,DBNAME,null,VERSION);}@OverridepublicvoidonCreate(SQLiteDatabasedb){db.execSQL("createtableperson(_idintegerprimarykeyautoincrement,namevarchar(50),ageinteger)");}@OverridepublicvoidonUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion){db.execSQL("droptableifexistsperson");onCreate(db);}}案例:采用SQLiteOpenHelper封裝(二)業(yè)務類:
privateDataBaseOpenHelperdb;privateContextcontext;publicPersonBiz(Contextcontext){this.context=context;db=newDataBaseOpenHelper(context);}publicvoidsave(Personperson){SQLiteDatabasedatabase=db.getWritableDatabase();database.execSQL("insertintoperson(name,age)values(?,?)",newObject[]{person.getName(),person.getAge()});}publicvoidupdate(Personperson){SQLiteDatabasedatabase=db.getWritableDatabase();database.execSQL("updatepersonsetname=?,age=?where_id=?",newObject[]{person.getName(),person.getAge(),person.get_id()});}publicPersonfind(Integer_id){Personp=null;SQLiteDatabasedatabase=db.getReadableDatabase();Cursorc=database.rawQuery("sleect*frompersonwhere_id=?",newString[]{_id+""});while(c.moveToNext()){p=newPerson();p.set_id(c.getInt(0));p.setName(c.getString(1));p.setAge(c.getInt(2));}returnp;}案例:采用SQLiteOpenHelper封裝(三)publicvoiddelete(Integer...ids){SQLiteDatabasedatabase=db.getWritableDatabase();if(ids!=null&&ids.length>0){StringBuildersb=newStringBuilder();for(Integerid:ids){sb.append("?").append(",");}sb.deleteCharAt(sb.length()-1);database.execSQL("deletefrompersonwhere_idin("+sb+")",(Object[])ids);}}publicList<Person>getDataByPage(intstartResult,intmaxResult){List<Person>persons=newArrayList<Person>();SQLiteDatabasedatabase=db.getReadableDatabase();Cursorc=database.rawQuery("select*frompersonlimit?,?",newString[]{String.valueOf(startResult),String.valueOf(maxResult)});while(c.moveToNext()){persons.add(newPerson(c.getInt(0),c.getString(1),c.getInt(2)));}returnpersons;}publiclonggetCount(){SQLiteDatabasedatabase=db.getReadableDatabase();Cursorc=database.rawQuery("selectcount(*)fromperson",null);while(c.moveToNext()){returnc.getLong(0);}return0;}數(shù)據(jù)庫調(diào)試Sqlite3命令可以用于管理數(shù)據(jù)庫、查詢數(shù)據(jù)庫表結(jié)構(gòu)。AdbshellSqlite3/data/data/包名/databases/publisher.db使用.dump,select等命令查看數(shù)據(jù)庫.exit,退出.databases:查看當前數(shù)據(jù)庫.tables:.help案例:英文單詞生詞本要求:能將英文生詞添加到數(shù)據(jù)庫保存起來,可以查找單詞意思.示例代碼:生詞本設(shè)計一個數(shù)據(jù)庫實例AUTHOR_TABLE中定義作者的相關(guān)信息,主鍵為id。BOOK_TABLE中定義了書的相關(guān)信息,主鍵為id,通過author_id與AUTHOR_TABLE建立關(guān)聯(lián)。兩個表結(jié)構(gòu)的定義如下所示:獲取SQLiteDatabase實例獲取一個可讀的SQLiteDatabaseSQLiteDatabasedb=SQLOpenHelper.getReadableDatabase()獲取一個可寫的SQLiteDatabaseSQLiteDatabasedb=SQLOpenHelper.getWriteableDatabase()創(chuàng)建觸發(fā)器觸發(fā)器(Trigger)機制:在試圖對指定的數(shù)據(jù)表執(zhí)行指定的修改語句時,特定的數(shù)據(jù)操作將被自動執(zhí)行,實現(xiàn)關(guān)聯(lián)操作。db.execSQL("CREATETRIGGERbook_deleteDELETEON"+Publisher.AUTHOR_TABLE+""+"BEGIN"+"DELETEFROM"+Publisher.BOOK_TABLE+"WHERE"+Publisher.BOOK.AUTHOR_ID+"=old._id;"+"END;");//在數(shù)據(jù)庫升級時,應該在onUpdate方法中刪除已經(jīng)創(chuàng)建的觸發(fā)器db.execSQL("DROPTRIGERIFEXISTSbook_delete");創(chuàng)建索引索引(Index)是對數(shù)據(jù)表中一列或多列的值進行排序的一種結(jié)構(gòu)。使用索引可以更快地查找數(shù)據(jù),而不用讀取整個表。更新一個含有索引的表的時間要比更新沒有索引的表的時間長,因此,通常僅僅在經(jīng)常被檢索的列上創(chuàng)建索引。//建立了一個針對AUTHOR_TABLE表的NAME列的降序索引db.execSQL("CREATEINDEXauthorname_indexON"+Publisher.AUTHOR_TABLE+"("+Publisher.AUTHOR.NAME+""+DESC+");");
創(chuàng)建視圖視圖(View)用來表示一個或多個表中的記錄,可以在數(shù)據(jù)庫中生成虛擬表。視圖的創(chuàng)建過程中經(jīng)常使用到連接操作,通過該操作可以聯(lián)合查詢多個表。db.execSQL("CREATEVIEWIFNOTEXISTS"+Publisher.BOOK_AUTHOR_TABLE+"AS"+"SELECT"+Publisher.BOOK_TABLE+".*"+","+Publisher.AUTHOR.NAME+"FROM"+Publisher.BOOK_TABLE+"LEFTOUTERJOIN"+Publisher.AUTHOR_TABLE+"ON"+Publisher.AUTHOR_TABLE+"."+Publisher.AUTHOR._ID+"="+Publisher.BOOK_TABLE+"."+Publisher.BOOK.AUTHOR_ID);插入數(shù)據(jù)execSQL方法db.execSQL("INSERTINTO"+Publisher.AUTHOR_TABLE+"(author_name,address,phone)"+"VALUES("+"‵"+name+"',"+"'"+address+"',"+"'"+phone+"'"+")");insert方法ContentValuesvalues=newContentValues();values.put(Publisher.AUTHOR.NAME,name);values.put(Publisher.AUTHOR.ADDRESS,address);values.put(Publisher.AUTHOR.PHONE,phone);SQLiteDatabasedb=helper.getWritableDatabase();db.insert(Publisher.AUTHOR_TABLE,null,values);刪除數(shù)據(jù)execSQL方法db.execSQL("DELETEFROM"+Publisher.AUTHOR_TABLE+"WHERE"+AUTHOR._ID+"="+author_id);delete方法(不使用通配符)db.delete(Publisher.AUTHOR_TABLE,Publisher.AUTHOR._ID+"="+author_id,null);delete方法(使用通配符)db.delete(Publisher.AUTHOR_TABLE,Publisher.AUTHOR._ID+"=?",newString[]{String.valueOf(author_id)});更新數(shù)據(jù)execSQL方法db.execSQL("UPDATE"+Publisher.AUTHOR_TABLE+"SET"+AUTHOR.NAME+"='"+name+"'"+","+AUTHOR.ADDRESS+"='"+address+"'"+","+AUTHOR.PHONE+"='"+phone+"'"+"WHERE"+AUTHOR._ID+"="+id);update方法ContentValuesvalues=newContentValues();values.put(Publisher.AUTHOR.NAME,name);values.put(Publisher.AUTHOR.ADDRESS,address);values.put(Publisher.AUTHOR.PHONE,phone);SQLiteDatabasedb=helper.getWritableDatabase();db.update(Publisher.AUTHOR_TABLE,values,Publisher.AUTHOR._ID+"="+id,null);查詢數(shù)據(jù)SQLiteDatabase提供了Cursorquery(Stringtable,String[]columns,Stringselection,String[]selectionArgs,StringgroupBy,Stringhaving,StringorderBy)方法來實現(xiàn)查詢記錄.able代表查詢的數(shù)據(jù)表Columns代表要查詢的列數(shù)組election代表查詢的條件,可以使用“?”通配符selectionArgs代表selection表達式中的?roupBy代表數(shù)據(jù)分組Having代表哪些行顯示rderBy代表排序的方式Cursor
Cursor類用于對數(shù)據(jù)庫查詢的結(jié)果進行隨機的讀寫訪問。默認情況下Cursor的游標位于返回的所有數(shù)據(jù)行的前面。
Cursor常用方法如下:move(intoffset)將當前游標移動offset個位置。moveToFirst()將游標移動到第一行。moveToLast()將游標移動到最后一行。isLast()判斷游標是否在最后一行。isFirst()判斷游標是否在第一行。getPosition()獲得游標當前所在行的位置。getCount()獲得cursor中的所有行數(shù)。1SharedPreferences2文件4ContentProvider3課程目錄數(shù)據(jù)庫ContentProviderContentProvider概述創(chuàng)建ContentProviderContentProvider更新的通知機制訪問ContentProviderContentProvider概述ContentProvider允許應用程序之間共享數(shù)據(jù),通話記錄,多媒體數(shù)據(jù)等均是以ContentProvider的格式存儲。ContentProvider提供了一系列標準的方法接口。ContentProvider的數(shù)據(jù)可以使用文件、數(shù)據(jù)庫等多種方式存儲。每個ContentProvider都擁有一個通用資源標識符(URI)作為身份標識。ContentProvider的優(yōu)點當應用繼承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ù)訪問方式。Android平臺上常用的ContentProviderBrowser:讀取或修改標簽、瀏覽歷史和網(wǎng)絡(luò)搜索記錄;CallLog:讀取或修改通話記錄Contacts:讀取或修改聯(lián)系人信息;MediaStore:提供對多媒體文件(包括音頻、視頻等)的讀/寫控制,MediaStore中保存的文件可以全局訪問。Settings:讀取或修改設(shè)備設(shè)置信息。ContentProvider的數(shù)據(jù)模型ContentProvider以表格的形式將數(shù)據(jù)暴露給客戶端,每一行代表一條記錄。ContentProvider原理當一個應用程序需要把自己的數(shù)據(jù)暴露給其它程序使用時,該應用程序就可以通過提供ContentProvider來實現(xiàn);其它應用程序使用ContentResolver來操作ContentProvider暴露的數(shù)據(jù).一旦某個應用程序通過ContentProvider暴露了自己的數(shù)據(jù)操作接口,那么不管該應用程序是否啟動,其他應用程序都可以通過該接口操作該應用程序內(nèi)部的數(shù)據(jù).
使用ContentProvider向外發(fā)布共享數(shù)據(jù)當應用需要通過ContentProvider對外共享數(shù)據(jù)時,第一步需要繼承contentProvider并重寫下面方法:publicclassPersonContentProviderextendsContentProvider{ publicbooleanonCreate();publicURIinsert(Uriuri,ContentValuesvalues);publicintdelete(Uriuri,Stringselection,String[]selectionArgs);publicintudpate(Uriuri,ContextValuesvalues,Stringselection,String[]selectionArgs);publicCursorquery(Uriuri,String[]projection,Stringselection,String[]selectionArgs,StringsortOrder);publicStringgetType(Uriuri);}
第二步需要在AndroidManifest.xml使用<provider>對該ContentProvider進行配置,為了能讓其他應用找到該ContentProvider,ContentProvider采用了authorities(主機名/域名)對它進行唯一標識,你可以把ContentProvider看作是一個網(wǎng)站,authorities就是他的域名:<manifest….><applicationandroid:icon=“@drawable/icon”android:label=“@string/app_name”><providerandroid:name=“.PersonContentProvider”android:authorities=“vider.personprovider”/></application></manifest>配置注釋:.PersonContentProvider是類的名字authorities后面是域名案例:將生詞本向外發(fā)布ContentProvider的主要方法onCreate():在類創(chuàng)建后調(diào)用,android在系統(tǒng)啟動時就會創(chuàng)建ContentProvider.getType(Uriuri):返回當前Uri所代表數(shù)據(jù)的MIME類型。如操作的數(shù)據(jù)屬于集合類型,那么MIME類型字符串的開頭應為:vnd.android.cursor.dir/.例如:1.要得到所有person記錄的uri為:content://vider.PersonContentProvider/person,而返回的MIME類型字符串應為:vnd.android.cursor.dir/開頭2.要得到id為10的person記錄,Uri為content://vider.PersonContentProvider/person/10,而返回的MIME類型字符串應為:vnd.android.cursor.item/person
Uri介紹Uri代表了要操作的數(shù)據(jù),Uri主要包含兩部分信息:1.需要操作的ContentProvider的網(wǎng)站域名2.對ContentProvider中的什么數(shù)據(jù)進行操作
一個Uri由以下幾個部分組成:
content://vider.personprovider/person/10ContentProvider的schema已經(jīng)由Android所規(guī)定,
schema為:content://
主機名(或叫Authority)用于唯一標識這個ContentProvider,外部調(diào)用者可以根據(jù)這個標識來找到它。
路徑(path)/數(shù)據(jù)部分:可以用來表示我們要操作的數(shù)據(jù),路徑的構(gòu)建應根據(jù)業(yè)務而定,如下:
要操作person表中id為10的記錄,路徑:/person/10
要操作person表中id為10的記錄的name字段,路徑:/person/10/name
要操作person表中所有的記錄:/person
當然要操作的數(shù)據(jù)不一定來自數(shù)據(jù)庫,也可以是文件等其他存儲方式,如下:
要操作xml文件中person節(jié)點下的name屬性:/person/name
將一個字符串轉(zhuǎn)換成Uri,可以使用Uri類中的parse()方法Uriuri=Uri.parse(“content://vider.personprovier/person”);URIURI的組成為:<standard_prefix>://<authority>/<data_path>/<id>標準的前綴唯一標識整個ContentProvider描述了數(shù)據(jù)的路徑,確定返回哪類數(shù)據(jù)ID唯一標注請求的數(shù)據(jù)使用ContentResolver操作數(shù)據(jù)通過Context的getContentResolver()方法獲取ContentResolver對象.該對象有如下方法:insert(Uriuri,ContentValuesvalues):Delete(Uriuri,Stringwhere,String[]selectionArgs):Update(Uriuri,ContentValuesvalues,Stringwhere,String[]selectionArgs):Query(Uriuri,String[]projection,Stringselection,StringselectionArgs,Stringsortorder):UriMatcherAndroid平臺通過自帶的UriMatcher類來匹配當前ContentProvider中的URI,通過UriMatcher類的addURI方法來建立URI和指定數(shù)據(jù)種類的關(guān)系。addURI(Stringauthority,Stringpath,intcode)static{uriMatcher=newUriMatcher(UriMatcher.NO_MATCH);uriMatcher.addURI(PROVIDER_NAME,"authortable",AUTHORTABLE);uriMatcher.addURI(PROVIDER_NAME,"authortable/#",AUTHORTABLE_ID);uriMatcher.addURI(PROVIDER_NAME,"booktable",BOOKTABLE);uriMatcher.addURI(PROVIDER_NAME,"booktable/#",BOOKTABLE_ID);}創(chuàng)建ContentProvider的步驟確定用于存儲ContentProvider數(shù)據(jù)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025大豆買賣合同
- 2025房屋出租合同范本
- 2025品牌酒類買賣合同
- 物業(yè)公司保潔外包合同范本(7篇)
- 現(xiàn)代物流中的智能灌裝機技術(shù)應用探討
- 科技廚房中的智能餐具及其使用技巧
- 課題申報參考:跨文化傳播中的話語體系建設(shè)與國家形象塑造研究
- 教育游戲在促進學生合作學習中的作用
- 科技型企業(yè)的綠色實驗室建設(shè)策略
- 數(shù)學游戲在鞏固小學基礎(chǔ)知識中的作用
- 中華人民共和國保守國家秘密法實施條例培訓課件
- 管道坡口技術(shù)培訓
- 2024年全國統(tǒng)一高考英語試卷(新課標Ⅰ卷)含答案
- 2024年認證行業(yè)法律法規(guī)及認證基礎(chǔ)知識 CCAA年度確認 試題與答案
- 皮膚儲存新技術(shù)及臨床應用
- 外研版七年級英語上冊《閱讀理解》專項練習題(含答案)
- 2024年遼寧石化職業(yè)技術(shù)學院單招職業(yè)適應性測試題庫必考題
- 上海市復旦大學附中2024屆高考沖刺模擬數(shù)學試題含解析
- 幼兒園公開課:大班健康《國王生病了》課件
- 小學六年級說明文閱讀題與答案大全
- 人教pep小學六年級上冊英語閱讀理解練習題大全含答案
評論
0/150
提交評論