Android-持久化技术(一)

文件存储

文件存储是android中最基本的数据存储方式,不需要对存储的内容作任何的格式化处理,所有的数据会被原封不动的保存到文件当中,比较适合存储一些简单的文本文件或者是二进制文件。下面我们看一个简单的案例,分析存储和读取数据的具体实现。

将数据存储到文件中

先看代码:

        save.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                String data = "Data to save";

                FileOutputStream out = null;

                BufferedWriter bufferedWriter = null;

                try {

                    out = openFileOutput("data", Context.MODE_PRIVATE);

                    bufferedWriter = new BufferedWriter(new OutputStreamWriter(out));


                    bufferedWriter.write(data);

                    Toast.makeText(MainActivity.this,"数据存储完成",0).show();

                }catch (Exception e){


                    e.printStackTrace();

                    Toast.makeText(MainActivity.this,"数据存储失败",0).show();

                }finally {

                    try {

                        if (bufferedWriter != null){

                            bufferedWriter.close();
                        }

                    }catch (Exception e){

                        e.printStackTrace();

                    }

                }

            }
        });

代码分析:
通过openFileOutput()方法得到一个FileOutputStream对象,并依此构建OutputStreamWriter对象。然后借助OutputStreamWriter构建出BufferedWriter对象,通过BufferedWriter对象将文本内容写入。

从文件中读取数据

代码如下:

        read.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                FileInputStream input = null;

                BufferedReader reader = null;

                StringBuilder content = new StringBuilder();

                try {

                    input = openFileInput("data");

                    reader = new BufferedReader(new InputStreamReader(input));

                    String line = "";

                    while ((line = reader.readLine()) != null){

                        content.append(line);

                    }

                }catch (Exception e){

                    e.printStackTrace();

                }finally {

                    try{

                        if (reader != null){

                            reader.close();

                        }

                    }catch (Exception e){

                    }
                }

                Toast.makeText(MainActivity.this, "文本内容" + content,0).show();
            }
        });

首先通过openFileInput("data")方法获取到一个FileInputStream对象,然后借助它构建出一个InputStreamReader对象。我们就可以用过BufferedReader来逐行读取文件中的内容。

SharedPreferences

不同于文件存储方式,SharedPreferences是利用键值对来存储数据的。我们只需要在存储数据的时候,给本条数据对应的一个键值,则在去数据的时候就可以根据这个键来把值取出。
SharedPreferences支持多种不同类型的数据存储。例如:字符串,布尔,整形等。

可存储类型
使用SharedPreferences存储数据

要想使用SharedPreferences来存储数据,首先需要得到SharedPreferences对象。Android主要提供了3中方式用于得到SharedPreferences对象:
1、Context类的getSharedPreferences()
2、Activity的getPreferences()
3、PreferenceManager.getDefaultSharedPreferences()

主要实现步骤
1、调用SharedPreferences的edit()方法来获取SharedPreferences.Editor对象
2、向Editor对象中添加数据。
3、调用Editor的apply()方法提交数据,完成数据存储。

        spSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {


                SharedPreferences.Editor editor = getSharedPreferences("data",MODE_PRIVATE).edit();

                editor.putString("name","nameStr");

                editor.putInt("age", 20);

                editor.putBoolean("bool",false);

                editor.apply();
            }
        });
使用SharedPreferences读取数据

SharedPreferences的读取数据操作和其存储数据操作对应的,使用get方法把对应类型的数据读取出来相当的方便。android也为我们提供了读取多种类型数据的方法。

SharedPreferences读取数据

读取数据的实现要比存取数据的实现还要简单:

        spRead.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                SharedPreferences sp = getSharedPreferences("data",MODE_PRIVATE);

                String name = sp.getString("name","");

                Integer age = sp.getInt("age",0);

                Boolean bool = sp.getBoolean("bool",false);

                Log.d("MainActivity","name"+name+" age"+age+" bool"+bool);

            }
        });

SQLite数据库存储

SQLite是一款轻量级的关系型数据库,它的运算速度非常快,占用内存非常少,在移动端上使用也相当适合的。那么android中的SQLite是如何使用的呢?

android为我们专门提供了一个SQLiteOpenHelper抽象类,用来管理数据库,借助这个类就可以非常简单的对数据库进行创建和升级。
因为SQLiteOpenHelper是一个抽象类,我们需要创建一个自己的帮助类继承它。

SQLiteOpenHelper中有两个抽象方法:onCreate()和onUpgrade(),前者是实现数据库创建,后者是实现数据库升级的逻辑。
SQLiteOpenHelper还有两个非常重要的实例方法:getWritableDatabase()和getReadableDatabase(),两个方法都可以实现创建或者是打开一个现有数据库(如果数据库已经存在直接打开,如果数据库不存在的话先创建一个新的数据库),并返回一个可以对数据库进行读写的对象。

但是不同的是当数据库不可以写入的时候(例如:磁盘已满),getReadableDatabase()返回的数据库将以只读的方式打开数据库,而getWritableDatabase()方法则会出现异常。

创建数据库

我们下面尝试一个实例,来理解数据库的创建过程。

    public class MyDataBaseHelper extends SQLiteOpenHelper{

        //把建表语句定义成一个字符串常量
        public  static final String CREAT_BOOK = "create table Book("+
                "id integer primary key autoincrement, "+
                "auther 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 sqLiteDatabase) {

            //execSQL()完成执行语句操作(建表)
            sqLiteDatabase.execSQL(CREAT_BOOK);

            Toast.makeText(MainActivity.this,"create successed",Toast.LENGTH_SHORT).show();

        }
        
        //升级数据库
        //onUpgrade()方法主要用于对数据库进行升级
        @Override
        public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
        }
    }

紧接着,我们在MainActivity类中声明一个按钮createTable和helper。

private Button createTable;
private MyDataBaseHelper helper;

并在MainActivity的onCreate()方法中初始化

    createTable = (Button)findViewById(R.id.button05);
    helper = new MyDataBaseHelper(this,"BookStore.db",null,1);

按钮点击

        createTable.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                helper.getWritableDatabase();
            }
        });

针对以上代码:onCreate()方法中构建MyDataBaseHelper对象,通过构造函数将数据库名指定为BookStore.db指定数据库版本号为1,我们在createTable按钮的点击事件中调用getWritableDatabase()方法,即按钮在第一次点击的时候会首先判断BookStore.db数据库属否存在,不存在会创建BookStore.db数据库并调用MyDataBaseHelper的onCreate()方法, 如此一来Book表就能创建成功了,当我们在此点击按钮的时候就不会再创建数据库了

升级数据库

假如有这样一种情况,现有的数据库不能满足我们的需求了,我们现在需要在原有数据库的基础上加一张表,在这里以Category表为例。
我们在MyDataBaseHelper类中声明:

public  static final String CREAT_CATEGORY = "create table Category("+
                "id integer primary key autoincrement, "+
                "category_name text,"+"category_code integer)";

与此同时修改其onCreate()方法中的内容为

        @Override
        public void onCreate(SQLiteDatabase sqLiteDatabase) {
            //execSQL()完成执行语句操作(建表)
            sqLiteDatabase.execSQL(CREAT_BOOK);
            sqLiteDatabase.execSQL(CREAT_CATEGORY);
            Toast.makeText(MainActivity.this,"create successed",Toast.LENGTH_SHORT).show();
        }

点击创建数据库的按钮,结果并没有创建成功,因为数据库已经存在了,onCreate()方法并未执行。那么怎么解决呢?其实啊,我们只需要利用MyDataBaseHelper的升级功能,调用onUpgrade()方法执行一些操作,就能轻松解决这个问题。

        @Override
        public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

            sqLiteDatabase.execSQL("drop table if exists Book");

            sqLiteDatabase.execSQL("drop table if exists Category");

            onCreate(sqLiteDatabase);
        }

但是怎样才能启动onUpgrade()方法的执行呢?我们只需要在获取MyDataBaseHelper对象的时候,设置数据库的版本比之前的版本号大就OK了。

helper = new MyDataBaseHelper(this,"BookStore.db",null,2);
以上工作完成我们就实现了数据库的升级。

增、删、改、查

其实研究数据库是为我们服务的。能够实现数据的增、删、改、查才是我们最终的目的。其实利用SQLIte数据库实现增删改查的功能也是相当的简单。

        //向SQLite数据库添加数据
        insert.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                SQLiteDatabase db = helper.getWritableDatabase();

                ContentValues values = new ContentValues();

                values.put("name","liu gaojian");
                values.put("auther","gu hongjuan");
                values.put("pages",770);
                values.put("price",36.5);

                db.insert("Book",null,values);
                values.clear();

                values.put("name","zhao si");
                values.put("auther","liu neng");
                values.put("pages",520);
                values.put("price",1.5);

                db.insert("Book",null,values);

                Toast.makeText(MainActivity.this,"add data successed",Toast.LENGTH_SHORT).show();

            }
        });


        //更新数据
        update.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                SQLiteDatabase db = helper.getWritableDatabase();

                ContentValues values = new ContentValues();

                values.put("price",66.6);

                db.update("Book",values,"name = ?",new String[]{"zhao si"});

                Toast.makeText(MainActivity.this,"update data successed",Toast.LENGTH_SHORT).show();

            }
        });



        //删除数据
        delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                SQLiteDatabase db = helper.getWritableDatabase();

                db.delete("Book","pages > ?",new String[]{"600"});

                Toast.makeText(MainActivity.this,"delete data successed",Toast.LENGTH_SHORT).show();

            }
        });



        //查询数据
        select.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                SQLiteDatabase db = helper.getWritableDatabase();

                //查询db中的所有数据
                Cursor cursor = db.query("Book",null,null,null,null,null,null);

                if (cursor.moveToFirst()){

                    do {

                        //遍历cursor对象,取出数据并打印
                        String name = cursor.getString(cursor.getColumnIndex("name"));

                        String auther = cursor.getString(cursor.getColumnIndex("auther"));

                        int pages = cursor.getInt(cursor.getColumnIndex("pages"));

                        double price = cursor.getDouble(cursor.getColumnIndex("pages"));

                        Toast.makeText(MainActivity.this, "name:"+name+"auther: "+auther+"pages:"+pages+"price:"+price, Toast.LENGTH_SHORT).show();


                    }while (cursor.moveToNext());

                }
                cursor.close();
            }
        });

针对以上代码不做过多的解释,只提一点就是我们在进行查询操作的时候会用到query()方法,它有很多个参数,那么每个参数代表什么意义呢?

query方法的参数解释
直接使用SQL操作数据库

一些牛逼的人都是直接通过SQL操作数据库。下面我们举个简单的例子来看一下直接利用SQL是如何操作数据库的。

        select.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {


                SQLiteDatabase db = helper.getWritableDatabase();

                //添加数据
                db.execSQL("insert into Book (name, auther, pages, price) values(?, ?, ?, ?)", new String[]{"C语言","王二麻子", "334", "48.5"});
                db.execSQL("insert into Book (name, auther, pages, price) values(?, ?, ?, ?)", new String[]{"数据结构","习近平", "256", "49.9"});


                //更新数据
                db.execSQL("update Book set price = ? where name = ? ", new String[]{"5.49", "C语言"});


                //删除数据
                db.execSQL("delete from Book where pages > ?", new String[]{"500"});

                //查询数据
                db.rawQuery("select * from Book",null);

            }
        });
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342