为了账号安全,请及时绑定邮箱和手机立即绑定

Android Primer——数据存储方案 持久化技术

标签:
Android

所有应用程序必然有数据的输入输出,Android也是一样的,Android应用程序的参数设置、运行状态数据这些都需要保存到外部存储器上,保证关机后数据不丢失,如下是几种Android常见的数据存储方式: SharedPreferences:适合保存少量数据(一些配置信息、积分之类);SQLite:一个真正轻量级数据库,没有后台进程,整个数据库就对应于一个文件,适合大量数据需要存储、访问的情况。下来详细来看看它们的用法。Android系统主要提供了3种方式用于简单地实现数据持久化功能,即文件存储、SharedPreferences存储以及SQLite数据库存储。

1.文件存储

文件存储是Android中最基本的一种数据存储方式,它不对存储的内容做任何的格式化处理,所有数据都是原封不动地保存到文件当中,比较适合用于存储一些简单的文本数据或二进制数据,不适合存储一些较为复杂的文本数据。

1.将数据存储到文件中

Context 类提供了openFileOutput()方法,用于将数据存储到指定的文件中。所有的文件默认都是存储在 /data/data/< packagename>/files 目录下的。

public void save(String inputText) {
    FileOutputStream out = null;
    BufferedWriter writer = null;    try {        // 两种模式,MODE_PRIVATE:默认私有,指定相同文件名则覆盖原文件内容;MODE_APPEND:指定相同文件名则追加内容。
        // 其实还有MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE两种模式,因为安全因素已经在 Android4.2中被弃用。
        out = openFileOutput("data", Context.MODE_PRIVATE); 
        writer = new BufferedWriter(new OutputStreamWriter(out));
        writer.write(inputText);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {        try {            if (writer != null) {
                writer.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}123456789101112131415161718192021

2.从文件中读取数据

Context 类提供了openFileInput()方法,用于从文件中读取数据,只接受一个参数 文件名,系统会自动加载存储目录下的这个文件,并返回一个 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();
}123456789101112131415161718192021222324

2.SharedPreferences存储

不同于文件存储,SharedPreferences是使用 键值对 的方式来存储数据的。

1.SharedPreferences接口

主要负责读取应用程序的Preferences数据,提供了如下常见方法来访问SharedPreferences中的key-value对:

boolean contains(String key)             // 判断是否包含key对应的数据
abstract Map<String, ?> getAll()         // 获取全部key-value对
boolean getXxx(String key, xxx defValue) // 获取指定key的value值1234

2.将数据存储到SharedPreferences中

要想使用SharedPreferences来存储数据,首先需要获取到SharedPreferences对象,Android主要提供了3种方法用于获取SharedPreferences对象:

1)Context 类中的 getSharedPreferences()方法;
2)Activity 类中的 getPreferences()方法;
3)PreferenceManager 类中的 getDefaultSharedPreferences()方法。1234

SharedPreferences数据总是以xml格式存储在 /data/data/< packagename>/shared_prefs 目录下的。

// SharedPreferences接口本身没有写入数据的能力,而是通过内部接口,调用edit()方法即获取Editor对象SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
editor.putString("name", "USER_NAME");
editor.putInt("age", 25);
editor.apply(); // 除此之外,Editor对象还包含clear()和remove(String key)等方法12345

3.从SharedPreferences中读取数据

SharedPreferences pref = getSharedPreferences("data", MODE_PRIVATE);
String name = pref.getString("name", "");int age = pref.getInt("age", 0);123

3.SQLite数据库存储

SQLite是一个嵌入式的数据库引擎,适用于资源有限的设备上适量存取数据(SQLite数据库只是一个文件)。SQLiteDatabase表示一个数据库(底层是一个数据库文件),Android通过SQLiteDatabase对象来管理、操作数据库。

1.创建SQLite数据库

SQLiteDatabaseHelper类可用于管理数据库的创建和版本更新,SQLiteDatabaseHelper包含如下常用方法:

getReadableDatabase()        // 以读写的方式打开数据库对应的SQLiteDatabase对象
getWritableDatabase()        // 以写的方式打开数据库对应的SQLiteDatabase对象
onCreate(SQLiteDatabase db)  // 第一次创建回调
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)  // 当数据库版本更新时回调
close()                      // 关闭所有打开的SQLiteDatabase123456

继承SQLiteOpenHelper,创建MyDatabaseHelper数据库帮助类:

public class MyDatabaseHelper extends SQLiteOpenHelper {
    /**
     * integer表示整型,real表示浮点型,text表示文本类型,blob表示二进制类
     * primary key表示将id设为主键,并用auto_increment键字表示id是自增长的
     */
    private static final String CREATE_TABLE_PERSON = "create table person(" +            "id integer primary key autoincrement," +            "name text," +            "age integer)";    private Context mContext;    /**
     * 构造方法
     *
     * @param context 上下文
     * @param name 数据库名,创建数据库时使用的就是这里的名称
     * @param factory 允许我们在查询数据时返回一个自定义的Cursor,一般传入null
     * @param version 数据库版本号
     */
    public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory,                            int version) {        super(context, name, factory, version);
        mContext = context;
    }    /**
     * 创建数据库
     *
     * @param db
     */
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_TABLE_PERSON);
    }    /**
     * 升级数据库
     *
     * @param db
     * @param oldVersion
     * @param newVersion
     */
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }
}12345678910111213141516171819202122232425262728293031323334353637383940414243

然后就可以在应用程序中创建数据库了:

MyDatabaseHelper dbHelper = new MyDatabaseHelper(this, "person.db", null, 1);
dbHelper.getWritableDatabase();12

升级数据库只需要将版本号增加,然后 onUpgrade() 方法就可以被执行了。

2.SQLite数据库的增删改查

我们对数据库的操作无非4种:CRUD:

C  Create   添加  insert
R  Retrieve 查询  select
U  Update   更新  update
D  Delete   删除  delete12345

首先创建数据库表的实体类PersonBean:

public class PersonBean {
    private String name;    private int age;    public String getName() {        return name;
    }    public void setName(String name) {        this.name = name;
    }    public int getAge() {        return age;
    }    public void setAge(int age) {        this.age = age;
    }
}12345678910111213141516

前面我们知道,调用 SQLiteOpenHelper 的 getReadableDatabase() 或 getWritableDatabase() 方法可以用于创建和升级数据库的,不仅如此,这两个方法还都会返回一个 SQLiteDatabase 对象,借助这个对象就可以对数据进行 CRUD 操作了。

SQLiteDatabase db = dbHelper.getWritableDatabase();1

接下来将数据库person表的增删改查操作封装起来,如下PersonDB:

public class PersonDB {
    private MyDatabaseHelper dbHelper;    public PersonDB(Context context){
        dbHelper = new MyDatabaseHelper(context, "person.db", null, 1);
    }    /**
     * 增
     */
    public boolean add(PersonBean bean){
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put("name", bean.getName());
        values.put("age", bean.getAge());        /**
         * 执行插入,返回值(如果插入成功将插入成功的行号返回,失败返回-1)
         * table: 表名
         * nullColumnHack: 一般传null
         * values: 表中添加的一行的数据内容, ContentValues以Map封装
         */
        long result = db.insert("person", "null", values); // 内部在拼装sql语句
        // 关闭数据库
        db.close();        if (result == -1) {            return false;
        }        return true;
    }    /**
     * 删
     */
    public int delete(String name){
        SQLiteDatabase db = dbHelper.getWritableDatabase();        /**
         * table: 表名
         * whereClause: 删除条件
         * whereArgs: 删除条件占位符的参数
         * 返回值是: 成功删除了多少行
         */
        int result = db.delete("person", "name = ?", new String[]{name});        // 关闭数据库
        db.close();        return result;
    }    /**
     * 改
     */
    public int update(PersonBean bean){
        SQLiteDatabase db = dbHelper.getWritableDatabase();        /**
         * table: 表名
         * values: 更改字段的内容, 以map封装
         * whereClause: 更新条件
         * whereArgs: 更新条件占位符的参数
         * sql: update person set age=18 where name='zhangsan';
         */
        ContentValues values = new ContentValues();
        values.put("age", bean.getAge());        // 返回的值: 成功修改了多少行
        int result = db.update("person", values, "name = ?", new String[]{bean.getName()});        // 关闭数据库
        db.close();        return result;
    }    /**
     * 查
     */
    public PersonBean query(String name){
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        PersonBean bean = new PersonBean();        /**
         * table: 指定查询的表名
         * columns: 指定查询的列名(null:查询所有)
         * selection: 指定where的约束条件
         * selectionArgs: 为where中的占位符提供具体的值
         * groupBy: 指定需要group by的列
         * having: 对group by后的结果进一步约束
         * orderBy: 指定查询结果的排序方式
         */
        Cursor cursor = db.query("person", new String[]{"id","name","age"}, "name  = ?",                new String[] {name}, null, null, "id desc");        /**
         * 判断结果集中是否有数据
         */
        if(cursor != null && cursor.getCount() >0){            // 循环遍历结果集获取结果集的内容
            while(cursor.moveToNext()){                // 获取这一行上所有的数据内容
                int id = cursor.getInt(0);
                bean.setName(cursor.getString(1));
                bean.setAge(Integer.parseInt(cursor.getString(2)));
            }
        }        // 关闭数据库
        db.close();        return bean;
    }
}12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697

到此我们就可以通过创建PersonDB的实例,调用该实例的方法来增删改查数据库person表了:

PersonDB personDB = new PersonDB(context);// 增PersonBean bean = new PersonBean();
bean.setName("zhangsan");
bean.setAge(20);
personDB.add(bean);// 删personDB.delete("zhangsan");// 改PersonBean bean = new PersonBean();
bean.setName("zhangsan");
bean.setAge(25);
personDB.update(bean);// 查PersonBean bean = personDB.query("zhangsan");123456789101112131415

4.使用SQL操作数据库

首先打开数据库对应的 SQLiteDatabase 对象:

MyDatabaseHelper dbHelper = new MyDatabaseHelper(context, "person.db", null, 1);
SQLiteDatabase db = dbHelper.getWritableDatabase();12

然后我们就可以直接使用 SQL语句 操作数据库:

// 增db.execSQL("insert into person (name ,age) values (?, ?)", new String[]{"wangwu","26"});// 删db.execSQL("delete from person where age>?", new String[]{"20"});// 改db.execSQL("update person set age=? where name=?", new String[]{"19", "wangwu"});// 查db.rawQuery("select * from person", null);12345678

5.使用数据库开源库操作数据库

现在公司里的代码非常强调稳定性,而我们自己写出的代码往往结构越复杂就越容易出现问题,相反,开源项目的代码都是经过时间验证的,通常比我们自己的代码要稳定的多。因此,现在很多公司为了追求开发效率以及项目的稳定性,都会选择使用开源库。

数据库开源库说明地址
DBFlow一个基于AnnotationProcessing(注解处理器)的强大、健壮同时又简单的ORM框架https://github.com/Raizlabs/DBFlow
OrmLiteJDBC和Android的轻量级ORM java包https://github.com/j256/ormlite-android
Sugar用超级简单的方法处理Android数据库https://github.com/satyan/sugar
GreenDao一种轻快地将对象映射到SQLite数据库的ORM解决方案https://github.com/greenrobot/greenDAO
ActiveAndroid以活动记录方式为Android SQLite提供持久化https://github.com/pardom/ActiveAndroid
SQLBriteSQLiteOpenHelper和ContentResolver的轻量级包装https://github.com/square/sqlbrite
Realm移动数据库:一个SQLite和ORM的替换品https://github.com/realm/realm-java

原文链接:http://www.apkbus.com/blog-822715-78042.html

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消