Android数据持久化数据存储

xiaoxiao2021-02-28  71

三种:文件存储 SharePreference存储 数据库存储     当然 除了这三种还可以将数据存储在SD卡  网络上

本文主要探究前三种存储方式以及开源库 LitePal

一. 文件存储

将所有数据原封不动的保存到文件当中

适用于: 存储一些简单的文本数据或二进制数据

如何做: 通过 Context类的 openFileOutput() 方法  

两个参数:    

1.文件名不可以包含路径,默认存储到/data/data/<packagename>/files/目录下

2.文件操作模式       

2.1 MODE_PRIVATE 文件名相同时会覆盖原文件内容  

   2.2 MODE_APPEND  如果该文件存在,就向里面追加内容;,不存在就新建;

        下面两个4.2版本后因为可以让其他应用程序进行读写而存在安全性漏洞 已经废弃 

具体是: MODE_WORLD_READABLE 和 MODE_WORLD_WRITEABLE) 

返回FileOuputStream对象,得到此对象即可使用Java流的方式将数据写入文件

代码示例:

写入文件:

/** * 通过openFileOutput()方法获得一个FileOutputStream对象 * 再构建一个OutputStreamWriter对象 * 再使用OutputStreamWriter构建一个BufferWriter对象 * 通过BufferWriter将文本内容写入到文件中 */ 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(); } } } } 读取文件:

public String read(){ 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.存储 

存储路径:/data/data/<package name>/shared_prefs/

1.1获取Sharedpreference对象:

三种方式: 

a. Context类中的getSharedPreferences()方法

    b. Activity类中的getPreferences()方法

c. PreferenceManager 类中的 getDefaultSharedPreferences()方法

举例:

SharedPreferences.Editor editor = getSharedPreferences("data",MODE_PRIVATE).edit(); editor.putString("name","HaHa"); editor.putInt("number",18); editor.putBoolean("Human",true); editor.apply(); 2.读取:

SharedPreferences pref = getSharedPreferences("data",MODE_PRIVATE); String name = pref.getString("name",""); int number = pref.getInt("number",0); boolean human = pref.getBoolean("Human",false);

三.SQLite数据库存储

当需要存储大量复杂的关系型数据时可以用到

+:SQLite数据类型:     

integer  整型

real       浮点型

text       文本类型

blob      二进制类型

1.创建数据库  

利用Android提供的SQLiteOpenHelper 帮助类:

a.  SQLiteOpenHelper是一个抽象类  自己创建一个帮助类继承SQLiteOpenHelper并重写 onCreat() 和 onUpdate()方法 进而实现创建、升级数据库的逻辑

b.  SQLiteOpenHelper两个重要方法:getReadableDatabase() getWritableDatabase() 可以创建或打开一个数据库 注意存储空间满时报错

c. SQLiteOpenHelper有两个构造方法可供重写:

一般使用参数少的那个,包含四个参数,

分别是(Context, 数据库名, 查询数据时返回的一个自定义Cursor 一般写null就好, 当前数据库版本号 用于对数据库进行升级等操作)

构建好SQLiteOpenHelper 的实例后,再调用 getReadableDatabase() 和 getWritableDatabase() 创建数据库

实例: 

  创建名为 BookStore.db的数据库 并在此数据库中新建一张Book表

   创建MyDataBaseHelper

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,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 SQLite数据库 succeeded",Toast.LENGTH_SHORT).show(); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } } 调用:

private MyDataBaseHelper myDataBaseHelper; myDataBaseHelper = new MyDataBaseHelper(this,"BookStore.db",null,1); myDataBaseHelper.getWritableDatabase();

2.升级数据库

在MyDataBaseHelper中的onUpgrade方法中执行

例:

再添加一张 Category 表用于记录图书的分类 Category中有 id(主键) 分类名 分类代码几个列

将建表语句: 

create table Category( id integer primary key autoincrement, category_name text, category_code integer )

添加到 MyDataBaaseHelper中:

public static final String CREATE_CATEGORY = "create table Category(" +"id integer primary key autoincrement," +"category_name text," +"category_code integer"; @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); } 调用时: private MyDataBaseHelper myDataBaseHelper;myDataBaseHelper = new MyDataBaseHelper(this,"BookStore.db",null,2);//将版本号增加myDataBaseHelper.getWritableDatabase();

3.增删改查       

CRUD create  retrieve  update   delete  

SQLite: insert   select    update   delete

3.1添加数据 SQLiteDatabase中提供了一个insert()方法 

三个参数(表名,

在未指定添加数据情况下给某些可为空的列自动赋值NULL 一般直接传入null, 

Contentvalues对象 提供了一系列put方法重载,用于向ContentValues中添加数据)

SQLiteDatabase db = myDataBaseHelper.getWritableDatabase(); ContentValues values = new ContentValues(); //开始组装第一条数据 values.put("name","DaVinci"); values.put("author","bicaso"); values.put("pages","666"); values.put("price",10.16); db.insert("Book",null,values);// 插入/添加 第一条数据 values.clear(); //开始组装第二条数据 values.put("name","hahaha"); values.put("author","bicaso"); values.put("pages","888"); values.put("price",100.66); db.insert("Book",null,values);// 插入/添加 第二条数据 //附:这里只对Book表里其中四列数据进行了组装 id没有赋值 因为在创建表的时候 将id设置为自增长了 //SQLite语言添加数据 db.execSQL("insert into Book(name,author,pages,price) values(?,?,?,?)",new String[] {"DaVinci","hahaha","666","10.16"}); db.execSQL("insert into Book(name,author,pages,price) values(?,?,?,?)",new String[] {"mikailangqiluo","hahaha","888","100.66"});

3.2 删除数据

SQLiteDatabase db = myDataBaseHelper.getWritableDatabase(); db.delete("Book","pages>?",new String[]{"500"}); //SQLite语言 db.execSQL("delete from Book where pages > ?",new String[]{"500"});

3.3 更改数据

//参数: 表名 ContentValues对象 约束更新某一行或某几行的数据 SQLiteDatabase db = myDataBaseHelper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("price",18.88); //将价格price改变 db.update("Book",values,"name=?",new String[]{"DaVinci"});

//SQLite语言 db.execSQL("update Book set price = ? where name = ?",new String[]{"10.16","DaVinci"});

3.4 查询数据

/** * 参数: 1: table 表名 * 2: columns 用于指定查询那一列 不指定则查询所有列 * 3-4: selection selectionArgs 用于约束查询某一行或某几行数据 不指定则默认所有行数据 * 5: group by 指定需要去group by的列 不指定则表示不对查询结果进行group by操作 * 6: having 对group by后的数据进一步过滤 不指定则不过滤 * 7: orderBy 指定查询结果的排序方式 不指定则为默认 * * 调用query()方法后会返回一个Cursor对象 查询到的所有数据都将从这个对象中取出 */ SQLiteDatabase db = myDataBaseHelper.getWritableDatabase(); //查询Book中的所有数据 Cursor cursor = db.query("Book",null,null,null,null,null,null); if(cursor.moveToFirst()){ do{ // }while (cursor.moveToNext()); } cursor.close(); //SQLite 语言 db.rawQuery("select * fromBook",null);

四.LitePal

LitePal 开源Android数据库框架  采用对象关系ORM模式 将常用的数据库功能进行封装 具体参考:http://github.com/LitePalFramework/LitePal

4.1 配置 LitePal

因为大多数开源项目都会将版本提交到jcenter上 所以只需在app/build.gradle文件中声明该开源库

4.1.1 编辑build.gradle文件 在dependencies 闭包中添加:

dependencies { ... compile 'org.litepal.android:core:1.3.2' ... } 4.1.2 配置litepal.xml文件

右击 app/src/main 目录->New->Directory 创建assets目录 然后在assets目录下创建literal文件 添加内容如下:

dbname 指定数据库名

version  数据库版本号

list      标签用于指定所有的映射类型

<?xml version="1.0" encoding="utf-8"?> <litepal> <dbname value="BookStore"></dbname> <version value="1"></version> <list> <mapping class="com.demo.androidlearn01.Book"></mapping> </list> </litepal>

4.1.3 在AndroidManifest.xml中配置LitePalApplication  

android:name="org.litepal.LitePalApplication"

如果已经有了自定义的Application 只需在其中添加

private static Context context; 以及onCreate()方法中 context = getApplicationContext(); LitePalApplication.initialize(context);

4.2 使用LitPal

对象关系映射ORM 将面向对象的语言和面向关系的数据库之间建立一种映射关系

4.2.1 创建Book javabean类  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; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public int getPages() { return pages; } public void setPages(int pages) { this.pages = pages; } public String getName() { return name; } public void setName(String name) { this.name = name; } } 正式操作: 增删改查

Connector.getDatabase();//自动创建数据库 //增 1.如在Book表中添加 press 列 直接修改代码 添加一个press字段就好 get set // 2.添加一张category表 只需新建一个Category类 然后在litepal.xml中<mapping ...></mapping> 添加 以及更改version版本号 // 3.添加数据 让Book类 继承 DataSupport :进行CRUD时必须继承 Book book = new Book(); book.setName("DaVinci"); book.setPages(666); book.setAuthor("lalala"); book.setPrice(12.34); book.setPress("Unkonw"); book.save(); //删 DataSupport.deleteAll(Book.class,"price<?","15"); //改 //更新 Book book1 = new Book(); book1.setName("DaVinci1"); book1.setPages(999); book1.setAuthor("lalala"); book1.setPrice(22.34); book1.setPress("Unkonw"); book1.save(); book1.setPrice(32.34); book1.save(); Book book2 = new Book(); book2.setPrice(42.34); book2.setPress("Auto"); book2.updateAll("name = ? and author = ?","DaVinci","lalala"); //注意 当把字段改为默认值时 是不能用set方法的 而是: Book book4 = new Book(); book4.setToDefault("pages"); book4.updateAll(); //查 List<Book> books = DataSupport.findAll(Book.class);

List<Book> books1 = DataSupport.select("name","author").find(Book.class);//查询指定name author 两列数据 List<Book> books2 = DataSupport.where("pages > ?","400").find(Book.class);//查询页数大于400的数据 List<Book> books3 = DataSupport.limit(2).find(Book.class);//只查询前2条数据 List<Book> books4 = DataSupport.limit(3).offset(1).find(Book.class);//查询表中 第2,3,4条数据 offset为位置偏移 //也可以通过连缀组合完成复杂查询 下面这段表示查询Book表中 第11——20条 页数大于300 的name author pages这3列数据 并按照页数升序排列 List<Book> books5 = DataSupport.select("name","author","pages") .where("pages > ?","300") .order("pages") .limit(10) .offset(10) .find(Book.class); //当然 LitePal也支持原生的SQLite进行查询 Cursor cursor = DataSupport.findBySQL("select * from Book where pages > ? and price > ?","300","200");

转载请注明原文地址: https://www.6miu.com/read-27631.html

最新回复(0)