Android开发基础知识整理之数据存储
2017-01-17 11:57
477 查看
本篇主要涉及Android中的数据持久化技术。
1. 获取FileOutputStream对象:使用Context类中的
文件默认存储到
两种操作模式可选:MODE_PRIVATE(默认)和MODE_APPEND 。
2. 构建出OutputStreamWriter对象,再借此构建出BufferedWriter对象,调用它的
1. 获取FileInputStream对象:使用Context类中的
SharedPregerences文件都存放在
操作模式只有MODE_PRIVATE可选,和传入0效果一样
Activity类中的
只接受一个操作模式参数,自动将当前活动类名作为文件名
PreferenceManager类中的
是一个静态方法,接收一个context参数,使用当前应用程序包名作为前缀来命名文件
(1) 调用SharedPreferences对象的
(2) 向Editor对象中添加数据,根据数据类型调用
(3) 调用
SQLiteOpenHelper的构造方法接收4个参数:(Context, 数据库名, null, 版本号)。第三个参数允许在查询数据时返回一个自定义Cursor,一般传入null。
两个实例方法
数据库文件存放在
2.
3. 修改MainActivity中构造方法的版本号,使
第二个参数用于在未指定数据的情况下给某些为空的列自动赋值NULL,一般用不到直接传入null;
第三个参数的ContentValues对象提供一系列
第二个参数中把要更新的数据组装进来;
第三个参数用于约束更新某一行或某几行的数据,对应SQL语句的where部分,包含占位符,例如”name = ?”;
第四个参数用一个字符串数组指定占位符的内容,如
和insert类似,第二三个参数用于约束删除某一行或某几行数据。
1. 使用
2. 查询完得到一个Cursor对象,调用
3. 通过一个循环遍历查询到的每一行数据,循环中可以通过Cursor的
4. 最后调用
更新数据
删除数据
查询数据
配置litepal.xml。在app/src/main下创建一个assets目录,在其中创建一个litepal.xml文件,编辑其中内容:
AndroidManifest中配置LitePalApplication。
(2) 将创建的类添加到映射模型列表中,使用
(3) 调用
注意:要更新为默认值,使用
调用
通过连缀查询定制更多查询功能:
也支持使用原生SQL进行查询:调用
一、 文件存储
不对存储内容进行任何格式化处理,原封不动的保存到文件中。适合存储一些简单的文本数据或二进制数据。(一) 存储
1. 获取FileOutputStream对象:使用Context类中的 openFileOutput()
方法,接收两个参数:(文件名, 操作模式)。
文件默认存储到/data/data/<package name>/files/目录下;
两种操作模式可选:MODE_PRIVATE(默认)和MODE_APPEND 。
2. 构建出OutputStreamWriter对象,再借此构建出BufferedWriter对象,调用它的 write
方法将数据写入文件。
public void save(String inputText) { FileOutputStream out = null; BufferedWriter writer = null; try { out =openFileOutput("data", Context.MODE_PRIVATE); // 获取FileOutputStream对象 writer = new BufferedWriter(new OutputStreamWriter(out); // 构建BufferedWriter对象 writer.write(inputText); } catch (IOException e) { e.printStackTrace(); } finally { try { if (writer != null) { writer.close() } } catch (IOException e) { e.printStackTrace(); } } }
(二) 读取
1. 获取FileInputStream对象:使用Context类中的 openFileInput(文件名)
方法。
2. 构建出InputStreamReader,再借此构建出BufferedReader对象,读取到StringBuilder中,最后返回。
public String load() { FileInputStream in = null; BufferedReader reader = null; StringBuilder content = new StringBuilder(); try { in = openFileInput("data"); // 获取FileInputStream对象 reader = new BufferedReader(new InputStreamReader(in)); // 构建BufferedReader对象 String line = ""; while ((line = reader.readLine()) != null) { content.append(line); // 逐行读取,若内容不为空添加到StringBuilder中 } } catch (IOException e) { e.printStackTrace; } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } return content.toString(); }
二、 SharedPreference存储
采用键值对的方式存储数据,支持多种不同的数据类型存储,使用XML格式来管理数据的。(一) 存储
1. 获取SharedPreferences对象,有三种方法:
Context类中的getSharePregerences(文件名, 操作模式)方法。
SharedPregerences文件都存放在
/data/data/<package name>/shared_prefs/目录下
操作模式只有MODE_PRIVATE可选,和传入0效果一样
Activity类中的
getPreferences(操作模式)方法。
只接受一个操作模式参数,自动将当前活动类名作为文件名
PreferenceManager类中的
getDeafaultSharedPreferences(context)方法。
是一个静态方法,接收一个context参数,使用当前应用程序包名作为前缀来命名文件
2. 向SharedPreferences文件中存储数据
(1) 调用SharedPreferences对象的 edit()
方法来获取一个SharedPreferences.Editor对象;
(2) 向Editor对象中添加数据,根据数据类型调用 putString()
、putBoolean()
等方法;
(3) 调用 apply()
方法提交数据。
SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit(); editor.putString("name", "Tom"); editor.putInt("age", 28); editor.putBoolean("married", false); editor.apply();
(二) 读取
使用getSring()、
getBoolean()等方法,接收两个参数:(键, 默认值)。
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数据库存储
适合存储大量复杂的关系型数据。(一) 创建数据库
借助抽象类SQLiteOpenHelper,继承此类后重写onCreate()、
onUpgrade()方法来创建和升级数据库。
SQLiteOpenHelper的构造方法接收4个参数:(Context, 数据库名, null, 版本号)。第三个参数允许在查询数据时返回一个自定义Cursor,一般传入null。
两个实例方法
getReadableDatabase()、
getWritableDatabase()用于创建或打开现有数据库,并返回一个可进行读写操作的对象。
数据库文件存放在
/data/data/<package name>/databases/目录下。
public class MyDatabaseOpenHelper extends SQLiteOpenHelper { public static final String CREATE_BOOK = "create table BOOK (" + "id integer primary key antoincrement, " // 设置为主键,自增长 + "author text" // text表示文本类型 + "price real, " // real表示浮点型 + "pages integer, " // integer表示整型 + "name text)"; private Context mContext; public MyDataBaseHelper(Context context, String name, SQLiteDatabase.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 AppCompatActivity { private MyDatabaseHelper dbHelper; @Override protected void onCreate(Bundle savedInstanceState) { ... dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1); Button createDatabase = (Button) findViewById(R.id.create_database); createDatabase.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dbHelper.getWritableDatabase(); } }); } }
(二) 升级数据库
1. 将建表语句添加到MyDatabaseHelper中;
2. onUpgrade()
中执行DROP语句,再调用 onCreate()
方法重新创建;
3. 修改MainActivity中构造方法的版本号,使 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); }
(三) 添加数据
使用SQLiteDatabase的insert()方法,接收三个参数:(要添加数据的表名, null, ContentValues对象)
第二个参数用于在未指定数据的情况下给某些为空的列自动赋值NULL,一般用不到直接传入null;
第三个参数的ContentValues对象提供一系列
put()方法重载用于向其中添加数据,传入 (列名, 待添加数据) 即可。
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(); // 开始组装第二条数据 ... db.insert("Book", null, valuse); // 插入第二条数据
(四) 更新数据
使用update()方法,接收四个参数:(表名, ContentValues对象, 约束语句, 字符串数组)。
第二个参数中把要更新的数据组装进来;
第三个参数用于约束更新某一行或某几行的数据,对应SQL语句的where部分,包含占位符,例如”name = ?”;
第四个参数用一个字符串数组指定占位符的内容,如
new String[] {"The Da Vinci Code"}。
SQLiteDatabase db = dbHelper.getWritaberDatabase(); ContentValues values = new ContentValues(); values.put("price", 10.99); db.update("Book", values, "name = ?", new String[] {"The Da Vinci Code"}); // 更新书名为"The Da Vinci Code"的数据
(五) 删除数据
使用delete()方法,接收三个参数:(表名, 约束语句, 字符串数组)。
和insert类似,第二三个参数用于约束删除某一行或某几行数据。
db.delete("Book", "pages > ?", new String[] {"500"}); // 删除页数超过500的书
(六) 查询数据
1. 使用 query()
方法,最短的方法重载接收七个参数;
2. 查询完得到一个Cursor对象,调用 moveToFirst()
将数据指针移动到第一行位置(返回True表示移动成功数据不为空);
3. 通过一个循环遍历查询到的每一行数据,循环中可以通过Cursor的 getColumnIndex()
方法获取到某一列在表中对应的位置索引,将其传入对应取值方法中就可以读取到数据了;
4. 最后调用 colse()
方法关闭Cursor。
query()方法参数 | 对应SQL部分 | 描述 |
---|---|---|
table | from table_name | 指定查询的表名 |
columns | select column1, column2 | 指定查询的列名 |
selection | where column = value | 指定where的约束条件 |
selectionArgs | - | 为where中的占位符提供具体值 |
groupBy | group by column | 指定需要group by的列 |
having | having column = value | 对group by后的结果进一步约束 |
orderBy | order by column1,column2 | 指定查询结果的排序方式 |
// 查询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();
(七) 使用SQL操作数据库
添加数据db.execSQL("insert into Book (name, author, pages, price) values(?, ?, ?, ?)", new String[] {"The Da Vinci Code", "Dan Brown", "454", "16.96"});
更新数据
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);
四、 使用LitePal操作数据库
LitePal是一款开源的Android数据库框架,它采用了对象关系映射(ORM)的模式,并对常用数据库功能进行了封装。(一) 配置LitePal
在app/build.grale文件中声明开源库的引用:compile 'org.litepal.android:core:1.4.1'
配置litepal.xml。在app/src/main下创建一个assets目录,在其中创建一个litepal.xml文件,编辑其中内容:
<?xml version = "1.0" encoding="utf-8"?> <litepal> <!-- 数据库名 --> <dbname value="BookStore" ></dbname> <!-- 数据库版本号 --> <version value="1" ></version> <!-- 指定所有映射模型 --> <list> </list> </litepal>
AndroidManifest中配置LitePalApplication。
<application android:name="org.litepal.LitePalApplication" ...> ... </application>
(二) 创建和升级数据库
1.创建数据库
(1) 根据要创建的表定义一个类,定义相应字段并生成对应的getter和setter方法;
(2) 将创建的类添加到映射模型列表中,使用<mapping>
标签;
(3) 调用 Connector.getDatabase()
创建数据库。
/** 根据Book表的内容定义Book类 */ public class Book{ private int id; private String author; private double price; private int pages; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } ... //生成各个字段对应的getter和setter方法 }
<!-- 添加到映射模型列表中 --> <list> <mapping class="com.example.litepaltest.Book"></mapping> </list>
@Override public void onClick(View v) { Connector.getDatabase(); // 创建数据库 }
2. 升级数据库
更改想要修改的任何内容,然后将版本号加1即可。升级会保留之前表中的所有数据。(三) 添加数据
创建出模型实例(要进行CRUD操作模型类必须继承字DataSupport类),调用set方法将所有要存储的数据设置好,最后调用save()方法即可。
public class Book extends DataSupport { ... }
Book book = new Book(); book.setName("The Da Vinci Code"); book.setAuthor("Dan Brown"); book.setPages(454); book.setPrice(16.96); book.setPress("UnKnow"); book.save():
(四) 更新数据
new出模型实例,调用set方法设置要更新的数据,最后调用updateAll()方法执行更新操作(updateAll中可以指定约束条件)。
注意:要更新为默认值,使用
setToDefault()方法。
/** 将书名为The Lost Symbol并且作者是Dan Brown的书价格更新为14.95,出版社更新为Anchor */ Bool book = new Book(); book.setPrice(14.95); book.setPress("Anchor"); book.updateAll("name = ? and author = ?", "The Lost Symbol", "Dan Brown");
/** 将所有书页更新为0(默认值) */ Book book = new book; book.setToDefault("pages"); book.updateAll();
(五) 删除数据
调用已存储对象(调用过save方法或通过LitePal提供的查询API查出来的对象)的delete()方法。
调用
DataSupport.deleteAll()方法,接收三个参数:(要删除数据的表名, 约束条件, 占位符内容)
/** 删除Book表中价格低于15的书 */ DataSupport.deleteAll(Book.class, "price < ?", "15");
(六) 查询数据
调用findAll()方法,返回值为对应类型的List集合。
List<Book> books = DataSupport.finAll(Book.class); for (Book book : books) { Log.d("MainActivity", "book name is " + book.getName()); Log.d("MainActivity", "book author is " + book.getAuthor()); Log.d("MainActivity", "book pages is " + book.getPages()); Log.d("MainActivity", "book price is " + book.getPrice()); Log.d("MainActivity", "book press is " + book.getPress()); }
findFirst()、
findLast()分别查询第一条和最后一条数据.
通过连缀查询定制更多查询功能:
方法 | 对应SQL部分 | 描述 |
---|---|---|
select() | select | 指定查询哪几列数据 |
where() | where | 指定查询的约束条件 |
order() | order by | 指定结果的排序方式(desc降序,asc或不写为升序) |
limit() | limit | 指定查询结果的数量 |
offset() | limit | 指定查询结果的偏移量 |
/** 查询Book表中第11~20条页数大于400的name、author、pages这三列数据,并将结果按页数升序排列 */ List<Book> books = DataSupport.select("name", "author", "pages") .where("pages > ?", "400") .order("pages") // 默认为asc升序 .limit(10) // 只查前10条 .offset(10) // 偏移10个位置 .find(Book.class);
也支持使用原生SQL进行查询:调用
DataSupport.findBySQL(SQL语句, 占位符的值),返回一个Cursor对象。
Cursor c = DataSupport.findBySQL("select * from Book where pages > ? and price < ?", "400", "20");
相关文章推荐
- [置顶] Android开发之数据存储——SharedPreferences基础知识详解,饿补学会基本知识,开发者必会它的用法。
- Android开发数据存储基础整理
- android-基础知识整理-数据存储(未完)
- Android应用开发基础之三:数据存储和界面展现(三)
- Android开发基础知识整理之多线程与网络技术
- Android开发基础知识整理之UI与Fragment
- 16、Android开发基础之把数据存储到SD卡上以及SD卡相关的API
- Android应用开发基础之数据存储和界面展现(一)
- Android游戏开发基础part9--游戏数据存储
- (android 基础知识之数据存储) ContentResolver
- Android游戏开发基础part9--游戏数据存储
- Android应用开发基础之一:数据存储和界面展现(一)
- android成长日记 11.详细学习了数据存储相关基础知识
- Android基础知识(6)—数据持久化之数据存储
- Android应用开发基础之数据存储和界面展现(二)
- 13、Android开发基础之数据存储-查看保存的数据
- iOS应用开发基础(四)基础知识(数据存储和多线程)
- 基础知识:android 数据存储--->文件存储
- 关于android中数据持久化存储的方法的知识整理
- Android游戏开发基础part9--游戏数据存储