Android 学习系列之 数据存储

数据持久化技术简介

数据持久化就是指将那些内存中的瞬时数据保存到存储设备中,保证即使在手机或电脑关机的情况下,这些数据仍然不会丢失。保存在内存中的数据是处于瞬时状态的,而保存在存储设备中的数据是处千持久状态的,持久化技术则提供了一种机制可以让数据在瞬时状态和持久状态之间进行转换。
Android系统中主要提供了3种方式用千简单地实现数据持久化功能,即文件存储、SharedPreference存储以及数据库存储。

文件存储

文件存储是Android中最基本的一种数据存储方式,它不对存储的内容进行任何的格式化处理,所有数据都是原封不动地保存到文件当中的,因而它比较适合用于存储一些简单的文本数据或二进制数据。如果你想使用文件存储的方式来保存一些较为复杂的文本数据,就需要定义一套自己的格式规范, 这样可以方便之后将数据从文件中重新解析出来。

将数据存储到文件中

Context类中提供了一个openFileOutput()方法, 可以用千将数据存储到指定的文件中。这个方法接收两个参数,第一个参数是文件名,在文件创建的时候使用的就是这个名称,注意这里指定的文件名不可以包含路径,因为所有的文件都是默认存储到/ data/ data//files/目录下的。第二个参数是文件的操作模式, 主要有两种模式可选,MODE_PRIVATE和MODE— APPEND。其中MODE—PRIVATE是默认的操作模式,表示当指定同样文件名的时候,所写入的内容将会覆盖原文件中的内容, 而MODE_ APPEND则表示如果该文件已存在,就往文件里面追加内容, 不存在就创建新文件。
openFileOutput ()方法返回的是一个F且eOutputStream对象, 得到了这个对象之后就可以使用Java流的方式将数据写入到文件中了。以下是一段简单的代码示例, 展示了如何将一段文本内容保存到文件中:

    public void save() {
        St ring data = "Data to save";
        FileOutputStream out = null;
        BufferedWriter writer = null;
        try {
            out = openFileOutput("data", Context.MODE_PRIVATE);
            writer = new BufferedWriter(new OutputStreamWriter(out));
            writer.write(data);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (writer != null) {
                    writer.close();
                } 
            }
            catch(IOException e){
                e.printStackTrace();
            }
        }
    }

从文件中读取数据

类似于将数据存储到文件中, Context类中还提供了一个openFileinput()方法, 用千从文件中读取数据。这个方法要比openFileOutput()简单一些, 它只接收一个参数, 即要读取的文件名, 然后系统会自动到/data/data//files/目录下去加载这个文件, 并返回一个FileinputStream对象, 得到了这个对象之后再通过Java流的方式就可以将数据读取出来了。

public String load()
    {
        FileInputStream in = null;
        BufferedReader reader = null;

        StringBuilder content = new StringBuilder();

        try
        {
            in = openFileInput("data");
            reader = new BufferedReader(new InputStreamReader(in));
            String line = " ";
            while ((line = reader.readLine()) != null)
            {
                content.append(line);
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally {
            if(reader != null)
            {
                try
                {
                    reader.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }

        return  content.toString();
    }

SharedPreferences存储

不同于文件的存储方式,SharedPreferences是使用键值对的方式来存储数据的。也就是说,当保存一条数据的时候,需要给这条数据提供一个对应的键,这样在读取数据的时候就可以通过这个键把相应的值取出来。而且SharedPreferences还支持多种不同的数据类型存储,如果存储的数据类型是整型,那么读取出来的数据也是整型的;如果存储的数据是一个字符串,那么读取出来的数据仍然是字符串。

将数据存储到Shared Preferences中

要想使用SharedPreferences来存储数据,首先需要获取到Sha redP references对象。Android中主要提供了3种方法用千得到SharedPreferences对象。

得到SharedPreferences对象

  1. Context类中的getSharedPreferences()方法
    此方法接收两个参数,第一个参数用千指定SharedPreferences文件的名称,如果指定的文件不存在则会创建一个,SharedPreferences文件都是存放在/ data/ data// shared_prefs/目录下的。第二个参数用千指定操作模式,目前只有MODE_PRVATE这一种模式可选,它是默认的操作模式, 和直接传入0效果是相同的, 表示只有当前的应用程序才可以对这个SharedPreferences文件进行读写。

  2. Activity类中的getPreferences()方法
    这个方法和Context中的getSharedPreferences()方法很相似,不过它只接收一个操作模式参数, 因为使用这个方法时会自动将当前活动的类名作为SharedPreferences的文件名。

  3. PreferenceManager类中的getDefaultSharedPreferences()方法
    这是一个静态方法,它接收一个Context参数, 并自动使用当前应用程序的包名作为前缀来命名SharedPreferences文件。

存储数据

得到了SharedPreferences 对象之后, 就可以开始向SharedPreferences文件中存储数据了, 主要可以分为3步实现。

(l)词用SharedPreferences对象的edit()方法来获取一个SharedPreferences. Editor对象。
(2)向SharedP references. Editor 对象中添加数据, 比如添加一个布尔型数据就使用putBoolean()方法, 添加一个字符串则使用putSt ring ()方法, 以此类推。
(3)调用apply()方法将添加的数据提交,从而完成数据存储操作。

SharedPreferences.Editor editor= getSharedPreferences("data",
MODE_PRIVATE). edit ();
editor. putString("name", "Tom");
editor.putInt ("age", 28);
editor. putBoolean ("married", false);
editor.apply();

读取数据

SharedPreferences pref = getSharedPreferences("data", MODE_PRIVATE);
String name = pref.getString("name", "");
int age = pref.getint("age", 8);
boolean married = pref.getBoolean("married", false);

首先通过getSharedPreferences()方法得到了SharedP references对象,然后分别调用它的getSt ring () 、getlnt()和getBoolean()方法, 去获取前面所存储的姓名、年龄和是否巳婚,如果没有找到相应的值, 就会使用方法中传入的默认值来代替.

SQLite 数据库存储

SQLite 是一款轻最级的关系型数据库,它的运算速度非常快,占用资源很少,通常只需要几百KB的内存就足够了,因而特别适合在移动设备上使用。SQLite不仅支持标准的SQL语法,还遵循了数据库的ACID事务,所以只要你以前使用过其他的关系型数据库,就可以很快地上手SQLite。而SQLite 又比一般的数据库要简单得多, 它甚至不用设詈用户名和密码就可以使用。Android 正是把这个功能极为强大的数据库嵌入到了系统当中, 使得本地持久化的功能有了一次质的飞跃。

创建数据库

Android为了让我们能够更加方便地管理数据库,专门提供了一个SQLiteOpenHelper 帮助类,借助这个类就可以非常简单地对数据库进行创建和升级。既然有好东西可以直接使用,那我们自然要尝试一下了,下面我就对SQLiteOpenHelper 的基本用法进行介绍。

首先你要知道SQLiteOpenHelper 是一个抽象类, 这意味着如果我们想要使用它的话,就需要创建一个自己的帮助类去继承它。SQLiteOpenHelper中有两个抽象方法,分别是onereate ()和onUpgrade () , 我们必须在自己的帮助类里面重写这两个方法, 然后分别在这两个方法中去实现创建、升级数据库的逻辑。

SQLiteOpenHelper 中还有两个非常重要的实例方法: getReadableDatabase()和getWritableDatabase()。这两个方法都可以创建或打开一个现有的数据库(如果数据库已存在则直接打开,否则创建一个新的数据库),并返回一个可对数据库进行读写操作的对象。不同的是,当数据库不可写入的时候(如磁盘空间已满),getReadableDatabase()方法返回的对象将以只读的方式去打开数据库, 而getWritableDatabase()方法则将出现异常。

SQLiteOpenHepl er中有两个构造方法可供重写, 一般使用参数少一点的那个构造方法即可。这个构造方法中接收4个参数, 第一个参数是Context, 这个没什么好说的, 必须要有它才能对数据库进行操作。第二个参数是数据库名,创建数据库时使用的就是这里指定的名称。第三个参数允许我们在查询数据的时候返回一个自定义的Cursor, 一般都是传入null 。第四个参数表示当前数据库的版本号, 可用于对数据库进行升级操作。构建出SQLiteOpenHelper的实例之后,再调用它的getReadableDatabase()或getWritableDatabase()方法就能够创建数据库了,数据库文件会存放在/ data / data/ / databases/目录下。此时,重写的onCreate()方法也会得到执行, 所以通常会在这里去处理一些创建表的逻辑。

实例
接下来还是让我们通过例子的方式来更加直观地体会SQLiteOpenHelper的用法吧, 首先新建一个Database项目。

这里我们希望创建一个名为BookStore.db的数据库,然后在这个数据库中新建一张Book表,表中有id(主键) 、作者、价格、页数和书名等列。创建数据库表当然还是需要用建表语旬的,这里也是要考验一下你的SQL基本功了,Book表的建表语旬如下所示:

create table Book (
id integer primary key autoincrement,
author text,
price real,
pages integer,
name text)

只要你对SQL方面的知识稍微有一些了解,上面的建表语旬对你来说应该都不难吧。SQLite不像其他的数据库拥有众多繁杂的数据类型, 它的数据类型很简单,integer 表示整型,real表示浮点型,text 表示文本类型,blob 表示二进制类型。另外, 上述建表语旬中我们还使用了primary key将过列设为主键, 并用autoincrement关键字表示过列是自增长的。

然后需要在代码中去执行这条SQL语旬, 才能完成创建表的操作。新建MyDatabaseHelper类继承自SQLiteOpenHelpre, 代码如下所示:

public class MyDatabaseHelper extends SQLiteOpenHelper {
    private static final String CREATE_BOOK = "create table Book ("
            + "id integer primary key autoincrement, "
            + "author text, "
            + "price real, "
            + "pages integer, "
            + "name text)";

    private Context context;

    public MyDatabaseHelper(Context context,String name, SQLiteDatabase.CursorFactory factory,int version)
    {
        super(context,name,factory,version);
        context = context;
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_BOOK);
        Toast.makeText(context,"Create successed",Toast.LENGTH_LONG).show();
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }
}

可以看到, 我们把建表语旬定义成了一个字符串常量, 然后在onCreate()方法中又调用了SQL iteDatabase的execSQL()方法去执行这条建表语旬, 并弹出一个Toast提示创建成功, 这样就可以保证在数据库创建完成的同时还能成功创建Book表。

建表:

private MyDatabaseHelper dbHelper;
dbHelper = new MyDatabaseHelper(this, "Bookstore.db", null, 1);
dbHelper.getWritableDatabase();

第一 次点击Create database按钮时, 就会检测到当前程序中并没有BookStore.db 这个数据库, 于是会创建该数据库并调用MyDatabaseHelper中的onCreate()方法, 这样Book表也就得到了创建, 然后会弹出一个Toast提示创建成功。再次点击Create database按钮时, 会发现此时已经存在Bookstore.db数据了, 因此不会再创建一次。

升级数据库

onUpgrade ()方法是用于对数据库进行升级的,它在整个数据库的管理工作当中起着非常重要的作用。
目前DatabaseTest项目中已经有一张Book表用千存放书的各种详细数据,如果我们想再添加一张Category表用于记录图书的分类, 该怎么做呢?

比如Category表中有id (主键)、分类名和分类代码这几个列, 那么建表语句就可以写成:

create table Category (
id integer primary key autoincrement,
category—name text,
category_code integer)

接下来我们将这条建表语句添加到MyDatabaseHelper中,代码如下所示:

//添加建表语句
public static final String CREATE_CATEGORY = "create table Category("
+ "id integer primary key autoincrement, "
+ "category_name text, "
+ "category_code integer)";

//修改onCreate
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE BOOK);
db.execSQL(CREATE CATEGORY);
Toast .makeText (mContext, "Create succeeded", Toast. LENGTH_SHORT). show();
}

//修改onUpgrade
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table if exists Book");
db.execSQL("drop table if exists Category");
onCreate(db);
}

//执行onUpgrade
dbHelper = new MyDatabaseHelper(this, "Bookstore.db", null, 2);

添加数据

SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("name","The Da Vinci Code");
values.put("author","Dan Brown");
values.put("pages",454);
values.put("price",16.95);
db.insert("Book",null,values);
values.clear();

更新数据

SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("price",10.99);
db.update("Book",values,"name = ?", new String[]{"The Da Vinci Code"});

删除数据

SQLiteDatabase db = dbHelper.getWritableDatabase();
db.delete("Book", "pages>?", new String[] { "588" });

查询数据

Cursor cursor = db.query("Book",null,null,null,null,null,null);
if(cursor.moveToFirst())
{
	 do {
	     String name = cursor.getString(cursor.getColumnIndex("name"));
	     String author = cursor.getString(cursor.getColumnIndex("author"));
	     int pages = cursor.getInt(cursor.getColumnIndex("pages"));
	     double price = cursor.getDouble(cursor.getColumnIndex("price"));
	     Log.e(TAG, "book name is"+ name);
	     Log.e(TAG, "book author is"+ author);
	     Log.e(TAG, "book pages is"+ pages);
	     Log.e(TAG, "book price is"+ price);
	 } while (cursor.moveToNext());
}
cursor.close();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值