第1章在Android系统中存储数据_第1页
第1章在Android系统中存储数据_第2页
第1章在Android系统中存储数据_第3页
第1章在Android系统中存储数据_第4页
第1章在Android系统中存储数据_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

·PAGE16·Android数据库程序设计·PAGE3·第1章在Android系统中存储数据第1章在Android系统中存储数据今天,我们生活在一个越来越多地依赖以数据为中心和数据驱动的世界当中。如亚马逊之类的公司对用户查看和购买的商品进行信息跟踪,以便能够向用户推荐更多类似产品;如Google这样的公司,存储通过它搜索的每一条查询,以便在未来能够提供更好的搜索查询建议;类似Facebook这样的社交媒体网站会记录用户与朋友之间的每一个事件,以便更好地了解数以百万计的用户。我们生活在以数据为中心的世界,开发以数据为中心的应用程序正是我们的当务之急。读者可能会问,为什么会是Android?或者再通俗点,为什么会是移动应用程序?在过去几年中,智能手机和平板电脑等移动设备使用量一直呈爆炸式的增长。此外,移动设备也隐含地给予在桌面应用程序当中所不具备的另一层面上的数据。当随身携带智能手机或平板电脑时,会通过这些设备得到当前所处的位置,也能够知道在何处办理手续或者在做些什么事情。简而言之,它所了解的可能比人们所能够意识到的更多。记住以上两点之后,现在使用Google已经内置在Android操作系统当中的多种方法来探索数据以及Android系统本身。本书假定读者都已经具有一些Android操作系统方面的相关经验,因此在这里将会深入到具体的代码层面上。但同样重要的是读者要知道所有可用的各种数据存储方法,还需要理解每一种方法的优劣,这样才能够创建高效的、易于设计和可伸缩的应用程序。1.1使用SharedPreferencesSharedPreferences是Android应用程序中存储本地数据最简单、快速和高效的方法。它的本质是一个框架,允许用户存储并关联每一个key-value(键-值)对到用户的应用程序(可以认为是映射到应用程序,以便用户可以随时访问)。此外,由于每个应用程序都与自己的SharedPreferences类相关联,因此被存储以及提交的数据将会在所有用户会话当中得以体现。然而,由于其简单和高效的性质,SharedPreferences只允许用户存储原始数据类型,即boolean(布尔型)、float(浮点型)、long(长整型)、int(整型)和string(字符型),因此在决定使用SharedPreferences存储数据时要牢记这一点。下面是如何访问和使用应用程序的SharedPreferences类的一个例子。publicclassSharedPreferencesExampleextendsActivity{ privatestaticfinalStringMY_DB="my_db"; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); //INSTANTIATESHAREDPREFERENCESCLASS SharedPreferencessp=getSharedPreferences(MY_DB, Context.MODE_PRIVATE); //LOADTHEEDITOR–REMEMBERTOCOMMITCHANGES! Editore=sp.edit(); e.putString("strKey","HelloWorld"); e.putBoolean("boolKey",true); mit(); StringstringValue=sp.getString("strKey","error"); booleanbooleanValue=sp.getBoolean("boolKey",false); Log.i("LOG_TAG","Stringvalue:"+stringValue); Log.i("LOG_TAG","Booleanvalue:"+booleanValue); }}首先来分析这段代码:在这里首先启动一个Activity;此外,在onCreat()方法中,请求检索SharedPreferences类。getSharedPreference()方法的语法是:getSharedPreferences(StringmapName,intmapMode)其中第一个参数指明了要映射的sharedpreference(每一个应用程序可以拥有几个单独的sharedpreference,因此,就像在数据库中指定表名一样,必须指明要检索的映射)。在上面的例子当中的第二个参数有点复杂,将MODE_PRIVATE作为参数,该参数只需指定要检索的shared

preference实例的可见性(在例子中可见性设置为私有,这样的话只有当前的应用程序才能访问映射的内容)。其他模式如下。MODE_WORLD_READABLE:映射的内容其他应用程序可见,但只读。MODE_WORLD_WRITEABLE:其他应用程序可对映射的内容进行读写。MODE_MULTI_PROCESS:该模式从APILevel11(Android3.0版本)开始提供,允许用户使用多个进程修改,可能会写入相同sharedpreference实例的映射。现在,只要有了sharedpreference对象,就可以立即使用各种get()方法对内容进行检索。例如前面提到的getString()和getBoolean()。get()方法通常有两个参数:第一个为key关键字,第二个参数在如果没有找到给定key关键字的情况下,则为默认值。在之前的那个例子当中,就是用了如下的get()方法:StringstringValue=sp.getString("strKey","error");booleanbooleanValue=sp.getBoolean("boolKey",false);因此,在第一种情况下所要检索的是与关键字strKey关联的字符,如果没有相关联的关键字,那么默认的字符串为error。类似地,在第二种情况下要检索与boolKey关键字相关联的布尔值,如果没有这样的键值存在,那么布尔值默认为false。然而,如果要编辑(edit)内容或添加新的(addnew)内容,还要检索每个sharedpreference实例包含的Editor对象。这个Editor对象包含所有允许用户传递键及其相关值(例如标准Map对象)的put()方法。唯一需要注意的是,在添加或更新了sharedpreference的内容后,需要调用Editor对象的commit()方法来落实更新。此外,就像一个标准的Map对象,Editor类也包含remove()和clear()方法,使用户可以自由操作sharedpreference的内容。在介绍使用SharedPreferences的典型用例之前,注意如果要将sharedpreference实例的可见性设置为MODE_WORLD_WRITEABLE,那么就可能会将自身暴露于那些有很多安全漏洞的众多外部恶意应用程序当中。因此在实际应用中并不推荐此模式。然而众多开发人员面临在两个应用程序间共享信息的需求,其解决的方法是在所涉及的应用程序清单文件中设置android:sharedUserID。它的工作原理是,每个应用程序在签名和导出时,会自动生成应用程序ID。如果在应用程序清单文件中明确设置了这个ID,假设两个应用程序使用相同的密钥进行签名,那么它们就不需要将其数据暴露给用户手机上其他应用程序能够自由地访问彼此的数据。换句话说,当两个应用程序设置了相同的ID,这两个(也只有这两个)应用程序可以访问彼此的数据。1.2SharedPreferences的常见使用案例现在已经知道如何实例化以及编辑一个sharedpreference对象,对这种类型的数据存储需要考虑它的典型用例。接下来的几个例子将会展示应用程序所保存的那些小型的、原始键-值数据对的类型。1.2.1检查用户是不是第一次访问应用程序大多数应用程序在用户第一次访问它时,会显示一些说明/向导或者启动画面的activity,如下所示:publicclassSharedPreferencesExample2extendsActivity{ privatestaticfinalStringMY_DB="my_db"; @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); SharedPreferencessp=getSharedPreferences(MY_DB, Context.MODE_PRIVATE); /** *CHECKIFTHISISUSER'SFIRSTVISIT */ booleanhasVisited=sp.getBoolean("hasVisited",false); if(!hasVisited){ //... //SHOWSPLASHACTIVITY,LOGINACTIVITY,ETC //... //DON'TFORGETTOCOMMITTHECHANGE! Editore=sp.edit(); e.putBoolean("hasVisited",true); mit(); } }}1.2.2应用程序最后一次更新时进行检查许多应用程序会有一些缓存或者同步、内建的功能等都可能会要求进行常规更新。要节省更新时间,可以快速检测距离上次更新已过去的时间,然后决定是否需要进行更新或同步,代码如下:/***CHECKLASTUPDATETIME*/longlastUpdateTime=sp.getLong("lastUpdateKey",0L);longtimeElapsed=System.currentTimeMillis()-lastUpdateTime;//YOURUPDATEFREQUENCYHEREfinallongUPDATE_FREQ=1000*60*60*24;if(timeElapsed>UPDATE_FREQ){//...//PERFORMNECESSARYUPDATES//...}//STORELATESTUPDATETIMEEditore=sp.edit();e.putLong("lastUpdateKey",System.currentTimeMillis());mit();下载本书例子的代码用户可以在Packt网站http://www.PacktP下载以用户并填写相关信息,将有电子邮件指引用户进行注册。1.2.3保存用户登录用户名一些应用程序允许记住用户自己的用户名(例如PIN、电话号码等其他面向登录的字段),使用sharedpreference是存储简单原始字符ID的好方法,代码如下:/***CACHEUSERNAMEASSTRING*///TYPICALLYYOUWILLHAVEANEDITTEXTVIEW//WHERETHEUSERENTERSTHEIRUSERNAMEEditTextuserNameLoginText=(EditText)findViewById(R.id.login_editText);StringuserName=userNameLoginText.getText().toString();Editore=sp.edit();e.putString("userNameCache",userName);mit();1.2.4保存应用程序的状态有些应用程序的功能可能会根据应用程序的状态发生变化。例如设置电话铃声的应用程序,当用户指明在静音时不启动任何程序,那么这个重要的状态需要被保存下来,如下所示:/***REMEBERINGACERTAINSTATE*/booleanisSilentMode=sp.getBoolean("isSilentRinger",false);if(isSilentMode){//...//TURNOFFAPPLICATION//...}1.2.5缓存用户的位置信息任何基于位置的应用程序都会有多种原因(可能是用户关掉了GPS,或者信号微弱等)要缓存用户最后所处的位置信息。这可以将用户的经纬度转换为一个浮点数后存储在sharedpreference实例当中简单地实现该功能,如下所示:/***CACHINGALOCATION*///INSTANTIATELOCATIONMANAGERLocationManagerlocationManager=(LocationManager)this.getSystemService(Context.LOCATION_SERVICE);//...//IGNORELOCATIONLISTENERSFORNOW//...LocationlastKnownLocation=locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);floatlat=(float)lastKnownLocation.getLatitude();floatlon=(float)lastKnownLocation.getLongitude();Editore=sp.edit();e.putFloat("latitudeCache",lat);e.putFloat("longitudeCache",lon);mit();在最新的Android版本(APILevel11,即Android3.0)中,提供了新的getStringSet()方法用于针对一个给定的关联键来设置和检索字符串对象集,其具体操作代码如下:Set<String>values=newHashSet<String>();values.add("Hello");values.add("World");Editore=sp.edit();e.putStringSet("strSetKey",values);mit();Set<String>ret=sp.getStringSet(values,newHashSet<String>());for(Stringr:ret){ Log.i("SharedPreferencesExample","Retrievedvals:"+r);}使用这种方法的例子很多,不过这里不得不暂时告一段落。1.3内部存储方法本节讲解Android的内部存储机制。对于那些具有标准Java编程经验的人来说,本节的内容会感觉到相当熟悉。Android的内部存储只允许读写与程序内部内存相关联的文件,这些文件只允许本应用程序访问,其他的应用程序或用户都不能访问。此外,当删除应用程序时,这些文件也会自动被删除。下面是如何访问应用程序内部存储的简单例子。publicclassInternalStorageExampleextendsActivity{ @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); //THENAMEOFTHEFILE StringfileName="my_file.txt"; //STRINGTOBEWRITTENTOFILE Stringmsg="HelloWorld."; try{ //CREATETHEFILEANDWRITE FileOutputStreamfos=openFileOutput(fileName, Context.MODE_PRIVATE); fos.write(msg.getBytes()); fos.close(); }catch(IOExceptione){ e.printStackTrace(); } }}这里简单地使用了Context类的openFileOutput()方法,该方法的第一个参数作为要创建(或覆盖)的文件名,第二个参数为其可见性(与SharedPreferences类似,可以控制文件的可见性)。这样它将会把想要写入的字符串转换为字节形式,并传递到输出流write()方法。另外,需要注意的是,在openFileOutput()方法中使用到另外一种模式,如下所示。MODE_APPEND:该模式允许用户打开现有的文件,并在原有内容的后面添加字符串(其他任何模式当中现有的内容将会被删除)。此外,如果在Eclipse中进行开发,可以转到DDMS界面中查看应用程序的内部文件(当中还包括其他一些内容),如图1-1所示。图1-1现在就可以看到刚才所创建的文本文件。在使用移动终端进行开发时,该文件的路径为/data/data/{your-app-path}/files/my_file.txt。然而,此时读取回来的文件会比较冗长,下面是处理的代码:publicclassInternalStorageExample2extendsActivity{ @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); //THENAMEOFTHEFILE StringfileName="my_file.txt"; try{ //OPENFILEINPUTSTREAMTHISTIME FileInputStreamfis=openFileInput(fileName); InputStreamReaderisr=newInputStreamReader(fis); //READSTRINGOFUNKNOWNLENGTH StringBuildersb=newStringBuilder(); char[]inputBuffer=newchar[2048]; intl; //FILLBUFFERWITHDATA while((l=isr.read(inputBuffer))!=-1){ sb.append(inputBuffer,0,l); } //CONVERTBYTESTOSTRING StringreadString=sb.toString(); Log.i("LOG_TAG","Readstring:"+readString); //CANALSODELETETHEFILE deleteFile(fileName); }catch(IOExceptione){ e.printStackTrace(); } }}在上面的代码中,首先打开文件输入流,并将其传递到流读取器。这可以调用read()方法,并且按照字节读取数据,这些数据随后可以附加到一个StringBuilder中。一旦内容充分读取,只需从StringBuilder中返回字符(String)即可。最后,出于完整性目的,Context类给用户提供了删除保存在内部存储中文件的简单方法。1.4外部存储方法外部存储,换句话说,就是将数据和文件存储到手机的外部SD(SecureDigital)卡SharedPreferences之间的利弊。由于shared

preference的开销较小,所以其读写到一个简单的Map对象的效率要比读写到磁盘的高。然而,因为仅限于简单的原始值(在大多数情况下,最新的Android版本允许用户保存字符串集),所以基本上就是针对效率去权衡其中的灵活性。基于内部存储和外部存储机制,用户可以不只是保存大块的数据(如整个XML文件),还可以是形式较为复杂的数据(如媒体文件、图像文件等)。那么内部存储和外部存储有什么区别?这两者的利弊较为微妙。一方面,在占用的存储空间(memory)上,虽然取决于用户所拥有的设备,但常见的内部内存大小往往会比较低,甚至是相对较新的手机的内部存储器空间也少于512MB(译者注:本书翻译时,手机内部存储器最大已经达到64GB)。另一方面,外部存储则根据用户在手机里使用什么样的SD卡来决定。通常情况下,如果使用了SD卡,则外部存储的容量会比内部存储大很多(根据SD卡的容量,其最大可达32GB)。现在,比较一下内部存储和外部存储的存取速度(accessspeed)。然而,在这种情况下,由于内部存储的读写速度完全依赖于手机使用的内部闪存类型来决定,外部存储也是这个道理,两者之间的比较并没有什么定论。最后需要考虑的一点是每种类型存储机制的可访问性(accessibility)。内部存储的数据只能由该应用程序访问,这就比让很多的外部恶意程序访问要安全得多。其缺点是一旦删除应用程序,那么内部内存的数据也会被擦除。对于外部存储,由于它的可见性是大范围的可读和可写,所以存储在其上的任何文件都暴露于外部应用程序和用户之下,这对文件的安全和可靠没有任何保证。现在我们已经了解了它们之间的一些不同点,接下来再次回到代码当中,用下面的例子看看如何去访问外部SD卡。publicclassExternalStorageExampleextendsActivity{ @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); StringfileName="my_file.txt"; Stringmsg="HelloWorld."; booleanexternalAvailable=false; booleanexternalWriteable=false; Stringstate=Environment.getExternalStorageState(); if(state.equals(Environment.MEDIA_MOUNTED)){ //HEREMEDIAISBOTHAVAILABLEANDWRITEABLE externalAvailable=true; externalWriteable=true; }elseif (state.equals(Environment.MEDIA_MOUNTED_READ_ONLY)){ //HERESDCARDISAVAILABLEBUTNOTWRITEABLE externalAvailable=true; }else{ //HEREFAILURECOULDBERESULTOFMANYSITUATIONS //NOOP } if(externalAvailable&&externalWriteable){ //FORAPILEVEL7ANDBELOW //RETRIEVESDCARDDIRECTORY Filer=Environment.getExternalStorageDirectory(); Filef=newFile(r,fileName); try{ //NOTEDIFFERENTFROMINTERNALSTORAGEWRITER FileWriterfWriter=newFileWriter(f); BufferedWriterout=newBufferedWriter(fWriter); out.write(msg); out.close(); }catch(IOExceptione){ e.printStackTrace(); } }else{ Log.e("LOG_TAG","SDCARDUNAVAILABLE"); } }}要执行上面的代码,需要将WRITE_EXTERNAL_STORAGE权限添加到清单文件中。这里首先开始调用Environment类的getExternalStorageState()方法,这样能够检测外部SD卡是否已经被装载并可写。在没有执行这些初步的检查之前就尝试(向外部SD卡)读写文件将引发错误。一旦确认SD卡已经被加载并且可写,在APILevel7(Android2.1)和较老的版本中,可以调用getExternalStorageDirectory()方法从SD卡的根目录上获取文件路径。这里只需创建新的文件,并实例化FileWriter和BufferedWriter,再将字符串写入文件即可。需要注意的是,这里处理外部存储写入磁盘时的方法不同于之前提到的写入内部存储磁盘的方法。这一点需要多加注意和理解,为此本书很注重这些写入方法。在内部存储的实例中通过调用Context类的openFileOutput()方法(该方法的第二个参数为模式)获得了FileOutputStream对象。当传递MODE_PRIVATE时后台则创建一个文件,并写入FileOutputStream,该文件由前述的应用程序唯一ID进行加密和签名,这样其他外部应用程序就不能随便访问这些文件的内容。但是,当在外部存储中创建和写入文件时,默认情况下它们并没有相关的强制安全机制,所以应用程序(或用户)可以直接对这些文件进行读写。这就是为什么用户可以使用标准的Java方法(如FileWriter)写入外部存储,而不能写入内部存储的原因。最后,注意在Eclipse的DDMS视图中创建的文件,假设安装了SD卡,可以很容易在DDMS中查看刚刚创建的文本文件,如图1-2所示。图1-2所以在开发应用程序时,通过DDMS视图可以很快地填入、取出以及监控写入磁盘的文件。紧接着介绍从APILevel8(Android2.2)版本后写入外部存储的一些变更。在http:///reference/android/content/Context.html#getExternalFilesDir(java.lang.String)网页中有这些变更的相关文档。但是在APILevel8(Android

2.2)和更高版本中,则会使用以下这两种主要的新方法:getExternalFilesDir(Stringtype)getExternalStoragePublicDirectory(Stringtype)可能会注意到此时能传递到类型参数的每一个方法。这些类型的参数允许用户指定文件的类型,以便分类到相应的子目录。上述第一种方法返回的外部文件目录的根是特定于用户应用程序的,以便在卸载应用程序时能够删除外部SD卡的关联文件。第二种方法的文件目录的根是公共的,以便在这些路径里的文件即使是在应用程序被卸载时还能保留。使用哪一种方法,取决于用户要保存的文件类型。例如,如果是要在应用程序中播放的媒体文件,那么用户在决定卸载应用程序时可能就不再需要该文件了。但是如果应用程序允许用户给自己的手机下载壁纸,那么在这种情况下,可能会考虑将这些图片文件保存到一个公共的目录,这样即使卸载了应用程序,那么这些文件还可以被系统所访问。在这里可以指定的不同类型(type)的参数如下:DIRECTORY_ALARMSDIRECTORY_DCIMDIRECTORY_DOWNLOADSDIRECTORY_MOVIESDIRECTORY_MUSICDIRECTORY_NOTIFICATIONSDIRECTORY_PICTURESDIRECTORY_PODCASTSDIRECTORY_RINGTONES在总结了对内部和外部存储机制的讨论后,接下来开始介绍SQLite数据库这个更重要的内容。1.5SQLite数据库同样重要的是,使用SQLite数据库是截止目前为止最先进和最强大的本地存储方法。每个应用程序都带有自己的SQLite数据库,可以被应用程序当中的任何类进行访问,而不能由外部程序访问。在介绍更复杂的查询或代码段之前,在这里先快速浏览一下SQLite数据库的要点。结构化查询语言(StructuredQueryLanguage,SQL)是专门用于在关系数据库中管理数据的编程语言。关系数据库允许用户提交插入、删除、更新和查询等操作,同时还允许创建和修改数据库模式(简单地说,就是数据库中的各个表)。SQLite是MySQL、PostgreSQL和其他较为流行的数据库系统的轻量化版本。它独立且不依赖于服务器,是事务性的,并能执行标准SQL语言查询。其独立性和可执行性使其显得高效而灵活,并且可在多种平台上使用各种编程语言进行访问(包括Android平台)。现在来看看如何实例化一个SQLite数据库模式,并且使用下面的代码片段来创建一个非常简单的表:publicclassSQLiteHelperextendsSQLiteOpenHelper{ privatestaticfinalStringDATABASE_NAME="my_database.db"; //TOGGLETHISNUMBERFORUPDATINGTABLESANDDATABASE privatestaticfinalintDATABASE_VERSION=1; //NAMEOFTABLEYOUWISHTOCREATE publicstaticfinalStringTABLE_NAME="my_table"; //SOMESAMPLEFIELDS publicstaticfinalStringUID="_id"; publicstaticfinalStringNAME="name"; SQLiteHelper(Contextcontext){ super(context,DATABASE_NAME,null,DATABASE_VERSION); } @Override publicvoidonCreate(SQLiteDatabasedb){ db.execSQL("CREATETABLE"+TABLE_NAME+"("+UID+" INTEGERPRIMARYKEYAUTOINCREMENT,"+NAME +"VARCHAR(255));"); } @Override publicvoidonUpgrade(SQLiteDatabasedb,intoldVersion, intnewVersion){ Log.w("LOG_TAG","Upgradingdatabasefromversion"+ oldVersion+"to"+newVersion+", whichwilldestroyallolddata"); //KILLPREVIOUSTABLEIFUPGRADED db.execSQL("DROPTABLEIFEXISTS"+TABLE_NAME); //CREATENEWINSTANCEOFTABLE onCreate(db); }}首先要注意的是:要创建可自定义的数据库模式,需要重写SQLiteOpenHelper类。重写该类后,接下来就可以重写允许改写表结构的onCreate()方法。在这个例子当中,仅创建了一个包含两个列的表:一个ID列和一个name列。这就等效于在SQL中运行如下命令:CREATETABLEmy_table(_idINTEGERPRIMARYKEYAUTOINCREMENT,nameVARCHAR(255));这里ID列指定为主键PRIMARYKEY,并且为自增量AUTOINCREMENT,这实际上是Android系统中在创建所有表时所推荐的操作,在这里将会一直按照该标准进行创建。最后,name列的宽度设置为最大255个字符(对于较长的字符串,可以将列设置为LONGTEXT,即长文本型)。在重写onCreate()方法之后,还要重写onUpgrade()方法。这些操作使用户能够快速而简单地修改表的结构。所需要做的就是自动增加DATA_VERSION的数值。在下次实例化SQLiteHelper时,它将会自动调用onUpgrade()方法,此时就会首先删除数据库的旧版本号,然后再创建新的版本号。最后,快速看一下如何在基本空白的数据表中插入记录和查询数值,如下所示:publicclassSQLiteExampleextendsActivity{ @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); //INITOURSQLITEHELPER SQLiteHelpersqh=newSQLiteHelper(this); //RETRIEVEAREADABLEANDWRITEABLEDATABASE SQLiteDatabasesqdb=sqh.getWritableDatabase(); //METHOD#1:INSERTUSINGCONTENTVALUECLASS ContentValuescv=newContentValues(); cv.put(SQLiteHelper.NAME,"jasonwei"); //CALLINSERTMETHOD sqdb.insert(SQLiteHelper.TABLE_NAME,SQLiteHelper.NAME, cv); //METHOD#2:INSERTUSINGSQLQUERY StringinsertQuery="INSERTINTO"+ SQLiteHelper.TABLE_NAME+ "("+SQLiteHelper.NAME+")VALUES('jwei')"; sqdb.execSQL(insertQuery); //METHOD#1:QUERYUSINGWRAPPERMETHOD Cursorc=sqdb.query(SQLiteHelper.TABLE_NAME, newString[]{SQLiteHelper.UID,SQLiteHelper.NAME},null,null, null,null,null); while(c.moveToNext()){ //GETCOLUMNINDICES+VALUESOFTHOSECOLUMNS intid=c.getInt(c.getColumnIndex(SQLiteHelper.UID)); Stringname= c.getString(c.getColumnIndex(SQLiteHelper.NAME)); Log.i("LOG_TAG","ROW"+id+"HASNAME"+name); } c.close(); //METHOD#2:QUERYUSINGSQLSELECTQUERY Stringquery="SELECT"+SQLiteHelper.UID+","+ SQLiteHelper.NAME+"FROM"+SQLiteHelper.TABLE_NAME; Cursorc2=sqdb.rawQuery(query,null); while(c2.moveToNext()){ intid= c2.getInt(c2.getColumnIndex(SQLiteHelper.UID)); Stringname= c2.getString(c2.getColumnIndex(SQLiteHelper.NAME)); Log.i("LOG_TAG","ROW"+id+"HASNAME"+name); } c2.close(); //CLOSEDATABASECONNECTIONS sqdb.close(); sqh.close();

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论