做项目肯定要考虑数据的存储,目前Android提供了3种方式用于简单的实现数据存储功能,即文件存储,SharePreference存储以及数据库存储。
文件存储
文件存储是Android中最基本的一种数据存储方式,所有的数据都会原封不动的保存到文件当中,比较适合存储一些简单的文本数据或二进制数据,如果你想存储较为复杂的文本数据,就需要定义一套自己的格式规范,方便以后将数据从文件中解析出来。
Context类提供了一个OpenFileOutput()方法,用于将数据存储到指定的文件中,这个方法接收两个参数,第一个参数是文件名,默认存储路径data/data/<package name>/fles/目录下的。第二个参数是文件的操作模式,主要有两种模式可选,MODE_PRIVATE和MODE_APPEND,其中MODE_PRIVATE是默认的操作模式,表示当指定同样文件已存在,所写入的内容将会覆盖原文件中的内容,而MODE_APPEND则表示如果该文件已存在,就往文件里面追加内容,不存在就新建新文件。其实文件的操作模式还有另外2种:MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE,这两种模式表示允许其他的应用程序对我们的程序中的文件进行读写操作,不过由于这两种模式过于危险,很容易引起应用的安全性漏洞,已在Android4.2版本中废弃。
下面我通过代码来讲解文件存储过程。
public void save(){
String value = "this is test";
FileOutputStream out = null;
BufferedWriter writer = null;
try{
out = openFileOutput("test",Context.MODE_PRIVATE);
writer = new BufferedWriter(new OutputStreamWriter(out));
writer.write(value);
} catch(IOException e) {
e.printStackTrace();
}finally{
try{
if (writer != null) {
writer.close();
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
这样我们就把数据存储到test文件中了,这个时候你肯定在想,存进去了,那么如何取出来呢?Context类中还提供了一个openFileInput()方法,用于数据的读取,系统会自动到/data/data/<package name>/files/目录下去加载这个文件,并返回FileInputStream对象。
public String load() {
FileInputStream in = null;
BufferedReader reader = null;
StringBuilder content = new StringBuilder();
try{
in = openFileInput("test");
reader = new BufferedReader(new InputStreamReader(in));
String line="";
while((line = reader.readLine()) ! = null) {
content.append(line);
}
}catch(IOException e) {
e.printStackTrace();
}finally{
if(reader!= null0 {
try{
reader.close();
} catch(IOException e){
e.printStackTrace();
}
}
}
return content.toString();
}
SharedPreferences存储
不同于文件的存储方式,SharedPreferences是使用键值对的方式来存储数据的。
将数据存储到SharedPreferences中
第一步我们需要获得SharedPreferences的对象,Android提供了3种方法。
1. Context类中的getSharedPreferences方法
此方法有2个参数,第一个参数指定SharedPreferences文件的名称,如果指定的文件不存在则会创建一个,第二个指定操作模式,目前只有MODE_PRIVATE可选,他是默认的操作模式,与直接传入0效果是相同的,表示只有当前的应用程序才可以对这个SharedPreferences文件进行读写,其他几种操作模式均已被废弃,MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE这两种模式实在Android4.2版本中被废弃的,MODE_MULTI_PROCESS模式是在Android6.0版本中被废弃的。
2. Activity类中的getPreferences()方法
与第一种方法类似,不过它只有一个参数,因为使用这个方法会自动将当前活动的类名作为SharePreferences的文件名。
3. PreferenceManager类中的getDefaultSharedPreferences()方法
这是一个静态方法,接收Context参数,并自动使用当前应用程序的包名作为前缀来命名SharedPreferences文件。
下面我用代码来讲解如何向SharedPreferences文件存储数据。
SharedPreferences.Editor editor = getSharedPreference("test",MODE_PRIVATE).edit();
editor.putString("name","Tom");
editor.putInt("age",28);
editor.putBoolean("married",false);
editor.apply();
将数据从SharedPreferences中取出来
SharedPreferences pref = getSharedPreference("test",MODE_PRIVATE);
String name = pref.getString("name","");
int age = pref.getInt("age",0);
boolean married = pref.getBoolean("married",false);
SQLite数据库存储
创建数据库
SQLiteOpenHelper中还有两个非常重要的实例方法,getReadableDatabase()和getWriteableDatabase().这两个方法都可以创建或打开一个现有的数据库。不同的是当数据库不可写入的时候,比如磁盘已满,getReadableDatabase()方法返回的对象将以只读的方式去打开数据库,而getWriteableDatabase()方法则会出现异常。
SQLiteOpenHelper中有两个构造方法可供重写,一般用参数少一点的那个就可以
super(context,"test.db",null,1);
下面我主要总结下如何用命令行查看数据库。
打开adb工具,输入adb shell就会进入到设备的控制台,如果你的命令行上显示时$符号,那么表示你现在是普通管理员,需要输入su命令切换成超级管理员,才能执行下面的操作。
然后使用cd命令进入到/data/data/包名/database/目录下,然后输入 sqlite3 test.db就可以对这个test数据库进行管理了,比如.table命令,可以查看数据中有几张表。.schema命令来查看他们的建表语句。
还可以写SQL语句查看数据库中的数据,比如select * from test,
我们可以键入.exit或.quit命令退出数据库的编辑,再键入exit命令就可以退出设备控制台。
其他的CRUD(增删改查)操作Android都提供了相应的方法,比较简单,我就不再一一介绍。有什么不懂的可以随时给我留言。
LitePal操作数据库
这是一个开源的Android数据库框架,用起来比SQLite更加方便,也是我今天总结的重点,它采用了对象关系映射(ORM)的模式。LitePal的项目主页上有详细的使用文档,点击查看
配置LitePal
需要在app/build.gradle文件,dependencies闭包中添加
compile 'org.litepal.android:core:1.4.1
这样我们就成功把LitePal引入到项目中了,接下来我们需要配置litepal.xml文件,右击app/src/main->New->Directory,创建一个assets目录,然后在assets目录下再新建一个litepal.xml文件,接下来我们来编辑这个内容
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<dbname value="test"></dbname>
<version value="1"></version>
<list>
</list>
</litepal>
这里面的标签含义应该不需要我解释,你一看应该就懂了。接下来我们需要配置一下LItePalApplication,修改 AndroidManifest.xml中的代码
<application
android:name="org.litpal.litepalApplication"
android:allowBackup=true
android:supportsRtl="true"
.......>
</application>
这样LItePal所有功能都可以正常工作了。
创建和升级数据库
我们以用户登录为例,需要在数据库中保存用户的账户密码,我们如何创建一个Account表呢?首先,我们定义一个JavaBean类,就叫Account吧
public class Account{
private String name;
private String password;
public String getName(){
return name;
}
public String setName(String name){
this.name = name;
}
public String getPassword(){
return password;
}
public String setPassword(String pw){
this.password = pw;
}
}
这个类就会对应数据库中的Account表,每个字段对应表中的每一列。
接下来,我们需要修改litepal.xml代码,如下所示
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<dbname value="test"></dbname>
<version value="1"></version>
<list>
<mapping class="com.example.litepaltest.Account"></mapping>
</list>
</litepal>
这样我们就把数据库和表创建出来了,这个时候你肯定会问如何调用才能创建呢?很简单
LitePal.getDatabase();
调用这行代码,数据库就会自动创建完成。
使用LitePal来升级数据库也非常简单,你完全不需要思考任何的逻辑,只需要修改你想改的内容即可,然后版本号加1就行。比如我们再添加一张表,
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<dbname value="test"></dbname>
<version value="2"></version>
<list>
<mapping class="com.example.litepaltest.Account"></mapping>
<mapping class="com.example.litepaltest.People"></mapping>
</list>
</litepal>
重新运行程序,调用Litepal.getDatabase()就升级成功了。
使用LitePal添加数据
LitePal进行表管理操作的时候我们不需要模型类有任何的继承结构,但是进行CRUD操作必须继承DataSupport类才行。然后我们只需要创建出模型类的实例,再将所有要存储的数据设置好,最后调用一下save()方法就可以了。下面我用代码说明。
Account account = new Account();
account.setName("June")
account.setPassword("123456")
account.save();这个save方法就是从DataSupport类继承而来的。
使用LitePal更新数据
对于LitePal来说,对象是否已经存储就是根据调用model.isSaved()方法的结果来判断的,返回true表示已存储,返回false表示未存储,实际上,只有两种情况model.isSaved()才会返回true,一种情况是已经调用过的model.save()方法去添加数据了,此时model就会被认为是已存储的对象,另一种情况是Model对象通过LitePal提供的查询API查出来的。
更新数据最笨的方法就是对已存储的对象重新设置,然后调用save.
Account account = new Account();
account.setName("June")
account.setPassword("123456")
account.save();
account.setName("July");
account.save();
这个时候数据库中存储的就是July而不是June.但是这种更新方式只对已存储的对象进行操作,限制性很大,下面我介绍一下另外一种更加灵巧的更新方式
Account account = new Account();
account.setPassword("666666")
account.updateAll("name = ?","June");
调用updateAll()方法去更新数据。如果不指定条件,那么就是更新所有数据,这里我们把June用户的密码改成了666666.
不过,在使用updateAll()方法时,如果你想把一个字段的值更新成默认值时,是不可以用上面的set()方法的,比如String的默认值是null,你如果调用account.setName(null)是不可以的,LitePal统一提供了一个setToDefault()方法,传入相应的列名就可以实现了
Account account = new Account();
account.setToDefalut("name")
account.updateAll();
这样所有用户的名字都会改为null.
使用LitePal删除数据
这个很简单,直接贴代码 DataSupport.deleteAll(Account.class,"name=","June");
这样就把叫June的用户删除了
使用LitePal查询数据
查找表中所有数据List<Account> accounts = DataSupport.findAll(Account.class);
查询表中第一条数据
Account firstUser = DataSupport.findFirst(Account.class);
查询表中最后一条数据
Account lastUser = DataSupport.findLast(Account.class);
select()方法用于指定查询那几列数据,对应SQL当中的select()关键字。
List<Account> users = DataSupport.select("name").find(Account.class);
where方法用于指定查询的约束条件,对应SQL当中的where关键字
List<Account> users = DataSupport.where("name=","June").find(Account.class);
order()方法用于指定结果的排序方式,对应SQL中的order by关键字
List<People> peoples = DataSupport.order("age desc").find(People.class);
limit()方法用于指定查询结果的数量
List<Account> users = DataSupport.limit(3).find(Account.class);
offest()方法用于指定查询结果的偏移量
List<Account> users = DataSupport.limit(3).offest(1).find(Account.class);
limt()和offest()对应SQL中的limit关键字
如果上述的这些api无法满足你的项目需求,则可以调用DataSupport.findBySQL()方法来进行原生查询,返回的是cursor对象,需要一一取出
Cursor cur = DataSupport.findBySQL("select * from People where age > ?","10")
今天就总结到这里吧,我写的相对比较简单,如果有什么看不懂的,欢迎随时给我留言
1498

被折叠的 条评论
为什么被折叠?



