Android第一行代码学习笔记四----数据存储

Android主要提供三种方式简单存储数据,即文件存储、SharedPreference 存储以及数据库存储。并且这三种存储方式比存储在SD卡中更安全。

一、文件存储

文件存储直接将数据保存到文件中,适用于简单的文本数据或二进制数据。
1、存储数据
Context 类中提供 openFileOutput ()方法,该方法接收两个参数,第一个参数是文件名,默认存储到/data/data/<packagename>/files/ 目 录 下 , 第 二 个 参 数 是 文 件 的 操 作 模 式 , 主 要 有 两 种  ,MODE_PRIVATE 和 MODE_APPEND。其中 MODE_PRIVATE 是默认的覆盖写入模式, MODE_APPEND 则表示如果该文件已存在就往文件里面追加内容,不存在就创建新文件。
示例代码如下:
public void save() {
String 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();
}
}
}
2、读取数据
Context 类中还提供了一个 openFileInput()方法用于读取数据,只接收一个参数,即要读取的文件名,然后系统会自动到/data/data/<package name>/files/目录下去加载这个文件,并返回一个FileInputStream 对象。
示例代码如下:
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使用键值对存储数据。
1、存储数据
首先获取到SharedPreferences对象,这里有三种方式。
1、Context 类中的 getSharedPreferences()方法
此方法接收两个参数,第一个参数指定 SharedPreferences 文件名称,如果指定的文件不存在则会创建一个,路径默认为/data/data/<packagename>/shared_prefs/目录。第二个参数指定操作模式,主要有两种,MODE_PRIVATE 和 MODE_MULTI_PROCESS。MODE_PRIVATE是默认的也可直接传入 0 ,表示只有当前的应用程序才可以对这个
SharedPreferences文件进行读写。 MODE_MULTI_PROCESS 则一般是用于会有多个进程中对同一个 SharedPreferences 文件进行读写的情况。
2、Activity 类中的 getPreferences()方法
getSharedPreferences()方法相似,不过它只接收一个操作模式参数,因为会自动将当前活动的类名作为 SharedPreferences 的文件名。
3、PreferenceManager 类中的 getDefaultSharedPreferences()方法
这是一个静态方法,它接收一个 Context 参数,并自动使用当前应用程序的包名作为前缀来命名 SharedPreferences 文件。
获得SharedPreferences对象之后, 存储数据步骤如下:
1、调用 SharedPreferences 对象的 edit()方法来获取一个 SharedPreferences.Editor 对象
2、向 SharedPreferences.Editor 对象中添加数据,比如添加一个布尔型数据就使用putBoolean 方法,添加一个字符串则使用 putString()方法
3、调用 commit()方法将添加的数据提交
示例如下:
public class MainActivity extends Activity {
private Button saveData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
saveData = (Button) findViewById(R.id.save_data);
saveData.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
SharedPreferences.Editor editor = getSharedPreferences("data",
MODE_PRIVATE).edit();
editor.putString("name", "Tom");
editor.putInt("age", 28);
editor.putBoolean("married", false);
editor.commit();
}
});
}
}
2、读取数据
根据存储数据类型使用对应get方法读取数据,有两个参数,第一个是键,第二个是找不到该键时返回的默认值。
示例如下:
public void onClick(View v) {
SharedPreferences pref = getSharedPreferences("data",
MODE_PRIVATE);
String name = pref.getString("name", "");
int age = pref.getInt("age", 0);
boolean married = pref.getBoolean("married", false);
Log.d("MainActivity", "name is " + name);
Log.d("MainActivity", "age is " + age);
Log.d("MainActivity", "married is " + married);
}

三、SQLite数据库存储

SQLite 是一款轻量级的关系型数据库,支持标准的 SQL 语法,还遵循了数据库的 ACID 事务。
1、创建数据库
SQLiteOpenHelper是一个抽象类,有两个抽象方法,分别是onCreate()和 onUpgrade(),我们必须在自己的帮助类里面重写这两个方法,去实现创建、升级数据库的逻辑。
该类还有两个重要实例方法,getReadableDatabase() 和getWritableDatabase()。这两个方法都可以创建或打开一个现有的数据库(如果数据库已存在则直接打开,否则创建一个新的数据库) ,并返回一个可对数据库进行读写操作的对象。不同的是,当数据库不可写入的时候(如磁盘空间已满)getReadableDatabase()方法返回的对象将以只读的方式去打开数据库,而 getWritableDatabase()方法则将出现异常。
SQLiteOpenHelper 中有两个构造方法可供重写,一般使用参数少一点的那个构造方法即可。接收四个参数,第一个是 Context,第二个是数据库名,第三个允许我们在查询数据的时候返回一个自定义的 Cursor,一般传入 null,第 四 个 表 示 当 前 数 据 库 的 版 本 号 , 可 用 于 对 数 据 库 进 行 升 级 操 作 。 构 建 出SQLiteOpenHelper 的实例后,调用它的 getReadableDatabase()或 getWritableDatabase()方法就能够创建数据库了,数据库文件会存放在/data/data/<package name>/databases/目录下。此时,重写的 onCreate()方法执行,所以通常会在这里去处理一些创建表的逻辑。
示例如下:
帮助类:
public class MyDatabaseHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK = "create table book ("
+ "id integer primary key autoincrement, "
+ "author text, "
+ "price real, "
+ "pages integer, "
+ "name text)";
private Context mContext;
public MyDatabaseHelper(Context context, String name, CursorFactory
factory, int version) {
super(context, name, factory, version);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
主类:
public class MainActivity extends Activity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);
Button createDatabase = (Button) findViewById(R.id.create_database);
createDatabase.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
dbHelper.getWritableDatabase();
}
});
}
}
2、升级数据库
示例:
public class MyDatabaseHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK = "create table Book ("
+ "id integer primary key autoincrement, "
+ "author text, "
+ "price real, "
+ "pages integer, "
+ "name text)";
第 2 章 先从看得到的入手,探究活动
247
public static final String CREATE_CATEGORY = "create table Category ("
+ "id integer primary key autoincrement, "
+ "category_name text, "
+ "category_code integer)";
private Context mContext;
public MyDatabaseHelper(Context context, String name,
CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
db.execSQL(CREATE_CATEGORY);
Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).
show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
在示例中,我们新增了表category,但是运行失败。因为此时数据库已经存在,因此onCreate()方法不会执行。
通过实现onUpgrade()方法
public class MyDatabaseHelper extends SQLiteOpenHelper {
……
@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);
}
}
此时就能调用onCreate语句。
要让onUpgrade()方法得到执行,只需要在SQLiteOpenHelper 构造参数中传入比之前版本号大的数字即可。之前传入1,现在传入2即可。
3、添加数据
调用 SQLiteOpenHelper的 getReadableDatabase()或 getWritableDatabase()方法会返回一个SQLiteDatabase对象,借助这个对象就可以对数据进行 CRUD 操作了。
SQLiteDatabase 中提供了一个 insert()方法,接收3个参数,第一个是表名,第二个用于在未指定添加数据的情况下给某些可为空的列自动赋值 NULL,一般我们用不到这个功能,直接传入 null ,第三个是一个 ContentValues 对象,它提供了一系列的 put()方法重载,用于向 ContentValues 中添加数据,只需要将表中的每个列名以及相应的待添加数据传入即可。
示例如下:
public class MainActivity extends Activity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
……
Button addData = (Button) findViewById(R.id.add_data);
addData.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
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.96);
db.insert("Book", null, values); // 插入第一条数据
values.clear();
// 开始组装第二条数据
values.put("name", "The Lost Symbol");
values.put("author", "Dan Brown");
values.put("pages", 510);
values.put("price", 19.95);
db.insert("Book", null, values); // 插入第二条数据
}
});
}
}
4、更新数据
SQLiteDatabase 中提供 update()方法用于更新数据。该方法有四个参数,第一个是表名,第二个是 ContentValues 对象,组装更新数据,第三四个用于去约束更新某一行或某几行中的数据,默认就是更新所有行。
示例:
public class MainActivity extends Activity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
……
Button updateData = (Button) findViewById(R.id.update_data);
updateData.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("price", 10.99);
db.update("Book", values, "name = ?", new String[] { "The Da
Vinci Code" });
}
});
}
}
5、删除数据
SQLiteDatabase 中delete()方法用于删除数据。接收三个参数,第一个是表名,第二、第三个用于去约束删除某一行或某几行的数据,默认删除所有行。
示例:
public class MainActivity extends Activity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
……
Button deleteButton = (Button) findViewById(R.id.delete_data);
deleteButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.delete("Book", "pages > ?", new String[] { "500" });
}
});
}
}
6、查询数据
SQLiteDatabase 提供query()方法查询数据。最短的一个方法重载也需要传入七个参数。第一个是表名,第二个指定查询哪几列,默认查询所有列,第三四个约束查询某一行或某几行的数据,默认是所有行,第五个指定需要去 group by 的列,不指定则表示不对查询结果进行 group by 操作。第六个参数用于对 group by 之后的数据进行进一步的过滤,不指定则表示不进行过滤。第七个参数用于指定查询结果的排序方式,不指定则表示使用默认的排序方式。

调用query()方法后会返回一个 Cursor 对象,查询到的所有数据都将从这个对象中取出。
示例:
public class MainActivity extends Activity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
……
Button queryButton = (Button) findViewById(R.id.query_data);
queryButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
// 查询Book表中所有的数据
Cursor cursor = db.query("Book", null, null, null, null, null, null);
if (cursor.moveToFirst()) {
do {
// 遍历Cursor对象,取出数据并打印
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.d("MainActivity", "book name is " + name);
Log.d("MainActivity", "book author is " + author);
Log.d("MainActivity", "book pages is " + pages);
Log.d("MainActivity", "book price is " + price);
} while (cursor.moveToNext());
}
cursor.close();
}
});
}
}
7、使用SQL操作数据库
db.execSQL("insert into Book (name, author, pages, price) values(?, ?, ?, ?)",
new String[] { "The Lost Symbol", "Dan Brown", "510", "19.95" });<pre name="code" class="java">db.execSQL("update Book set price = ? where name = ?", new String[] { "10.99",
"The Da Vinci Code" });
db.execSQL("delete from Book where pages > ?", new String[] { "500" });
db.rawQuery("select * from Book", null);
 查询用rawQuery方法,其他用execSQL。 
      
8、事务
示例:
public class MainActivity extends Activity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
……
Button replaceData = (Button) findViewById(R.id.replace_data);
replaceData.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.beginTransaction(); // 开启事务
try {
db.delete("Book", null, null);
if (true) {
// 在这里手动抛出一个异常,让事务失败
throw new NullPointerException();
}
ContentValues values = new ContentValues();
values.put("name", "Game of Thrones");
values.put("author", "George Martin");
values.put("pages", 720);
values.put("price", 20.85);
db.insert("Book", null, values);
db.setTransactionSuccessful(); // 事务已经执行成功
} catch (Exception e) {
e.printStackTrace();
} finally {
db.endTransaction(); // 结束事务
}
}
});
}
}
9、升级数据库的改善
前面只是简单的在onUpgrade()方法中删除掉了当前所有的表,然后强制重新执行了一遍 onCreate()方法,简单粗暴,这样会导致数据库中本身的数据丢失掉。通过对版本的合理控制,当数据库版本号大于当前数据库版本,则执行onUpgrade()方法,为每一个版本号赋予它各自改变的内容,然后在onUpgrade()方法中对当前数据库的版本号进行判断,再执行相应的改变。
以下为改善示例:
1、版本1:创建表Book
public class MyDatabaseHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK = "create table Book ("
+ "id integer primary key autoincrement, "
+ "author text, "
+ "price real, "
+ "pages integer, "
+ "name text)";
public MyDatabaseHelper(Context context, String name, CursorFactory
factory, int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
2、版本2:添加表Category
public class MyDatabaseHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK = "create table Book ("
+ "id integer primary key autoincrement, "
+ "author text, "
+ "price real, "
+ "pages integer, "
+ "name text)";
public static final String CREATE_CATEGORY = "create table Category ("
+ "id integer primary key autoincrement, "
+ "category_name text, "
+ "category_code integer)";
public MyDatabaseHelper(Context context, String name,
CursorFactory factory, int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
db.execSQL(CREATE_CATEGORY);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
case 1:
db.execSQL(CREATE_CATEGORY);
default:
}
}
}
说明:onCreate()中增加一条sql语句,onUpgrade()方法添加switch语句。如果是旧版本,则执行新的建表语句。
3、版本3:关联表,在Book表中添加category_id字段。
public class MyDatabaseHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK = "create table Book ("
+ "id integer primary key autoincrement, "
+ "author text, "
+ "price real, "
+ "pages integer, "
+ "name text, "
+ "category_id integer)";
public static final String CREATE_CATEGORY = "create table Category ("
+ "id integer primary key autoincrement, "
+ "category_name text, "
+ "category_code integer)";
public MyDatabaseHelper(Context context, String name,
CursorFactory factory, int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
db.execSQL(CREATE_CATEGORY);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
case 1:
db.execSQL(CREATE_CATEGORY);
case 2:
db.execSQL("alter table Book add column category_id integer");
default:
}
}
}
说明:修改Book建表语句,如果用户直接安装第3版则自动增加。如果是覆盖安装,则执行升级方法。注意,每一个case后面都没有break方法,保证每次跨版本升级,每一次数据库的修改都能被全部执行。













































  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值