Android持久化存储——(包含操作SQLite数据库) (一.)利用文件存储 (二.)利用 SharePreferences 存储 (三)利用SQL数据库存储

Android持久化存储——(包含操作SQLite数据库)
(一.)利用文件存储
(二.)利用 SharePreferences 存储
(三)利用SQL数据库存储

《第一行代码》读书手札


你可能会遇到的问题:解决File Explorer 中无显示问题


Android中,持久化存储,常见的一共有三种方法实现


文件存储是Android存储中,最基本的一种存储方式。

就是利用Context类的方法,获取输入输出字节流对象,之后,就是java的文件操作。

特点:

  1. 不对存储的数据进行任何格式化的处理

  2. 所有的数据,都原封不动的保存在文件中。

  3. 基于以上两点,文件存储只适合存储简单的文本数据

  4. 假如,非要存储一些复杂数据,就需要自己定义一套格式,便于将数据解析出来。

    简单说,就适合存储简单的数据文本,复杂的数据,请使用下面介绍的两种方法存储
    

a. 如何将数据存储到文件中

使用Context类的openFileOutput()方法,将数据存储到文本中,从名字也可

以看出来Output,将内存中的数据输出到硬盘中的,是用来保存数据的。


openFileOutput()方法


接受两个参数

  1. 第一个参数: 表示保存的文件的名字,这个名字中不能包含路径,因为所有的文件都是默认存

    储到 /data/data/<包名>files/ 目录下。

  2. 第二个参数: 表示文件的操作模式。目前只有两种模式了,其他模式由于安全性已经废弃了。

    MODE_PRIVATE :若文件已存在,则复写文件。

    MODE_APPEND :若文件已存在,则续写;文件不存在,就新建,再写文件。

返回值

1. 返回一个FileOutputStream 对象,就是java中的字节流对象,下面操作跟

java的IO流一样。

注意返回的是字节流,当我们操作的是文本数据,想使用字符流,需要转换流转换一下。

b.利用FileOutputStream对象,将数据存储到文件中

获取到FileOutputStream对象,存储文件,跟Java中一样。笔者,自定义一个save()方法,将数据存储到本地文件中。
    /**
     * 保存数据到文本中
     *
     * @param inputText 需要保存的文本
     */
    public void save(String inputText) {
        FileOutputStream out = null;
        BufferedWriter writer = null;

//      异常不能抛出去,因为活动的父类,没有抛出异常,作为子类也不能抛出异常
        try {
        //文件名中,不能包含路径
            out = openFileOutput("myData", Context.MODE_PRIVATE);
//           转换流
            writer = new BufferedWriter(new OutputStreamWriter(out));
//          将数据保存到本地
            writer.write(inputText);
//           刷新缓冲区
            writer.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
//            关闭缓冲区
            try {
                if (out != null) {
                    out.close();
                }
                if (writer != null) {
                    writer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

上述方法需要在活动的onDestory()中调用,在销毁活动的时候,将活动中的数

据,保存下来。

    在onDetory()方法中调用sava方法
    /**
     * 重写onDestory()方法
     * 在里面保存数据
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        String txt = edt_in.getText().toString();
    //文件为空,就不再保存
        if (!txt.equals(""))
            save(txt);

    }

c.从文本中读取数据

Context还提供了一个openFileInput()方法,返回一个FileInputStream对象,

接下来,就是跟java一样的操作。

    /**
     * 读取文件中的数据
     */
    public String load(){
//        Context的openFileInput()方法,返回一个字节流对象
        FileInputStream inputStream = null ;
//        字符操作,使用带缓冲区的字符流
        BufferedReader reader = null ;
//       字符串缓冲区,为了防止数据过多的情况下,频繁的创建字符串
        StringBuffer content = new StringBuffer() ;

        try {
//            获取字节流对象。参数为 文件名
//            它会自动的去保存的时候的路径
//            /data/data/<包名>files/ 目录下寻找
            inputStream = openFileInput("myData") ;
//            将字节流转换为带缓冲区的字符流
            reader = new BufferedReader(new InputStreamReader(inputStream)) ;
//           做标记,只要line不为null,就一直读取
//           顺便临时保留每次读取的行内容
            String line = "" ;
//            每次读取一行内容
            while((line = reader.readLine())!=null){
//                将读取的内容,保存到字符串缓冲区中
                content.append(line) ;
            }

        }catch (IOException e){
            e.printStackTrace();
        }
        return content.toString() ;
    }

d.恢复数据

b中,在活动被销毁的时候,将瞬时数据保存到本地文件中,那么,再次打开活动的时候,怎么将数据恢

复到活动中呢?

恢复数据,很简单,活动在第一次被创建的时候,一定会调用onCreate()方

法,我们就在这里,做恢复数据的工作。恢复之前,先做个判断,判读读取的数

据,是否为空串啥的。

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
//        获得控件对象
        edt_in = (EditText) findViewById(R.id.edt_in);
//        读取数据
        String input = load() ;
//          判断是否需要恢复数据
//          TextUtils.isEmpty(input) 
//          会判断是否为空串或者为null
        if(!TextUtils.isEmpty(input)){
//           非空就恢复数据
            edt_in.setText(input);
//            人性化操作,将输入的光标移动到文本末尾
            edt_in.setSelection(input.length());
        }

(二.)利用 SharePreferences 存储

特点:

1. 使用键值对存取数据

2. 保留数据原有格式,存进去的是整形,取出来的还是整形,

    与利用文件存储不一样,利用文件存储,会将所有数据,都当做字符串保存

3. 数据的存储,都是存储到文件中,这里是存储到SharePreferences文件中,该

文件是xml格式。


想要将数据存储到SharePreferences文件中,首先需要获取

SharePreferences对象,其中,SharePreferences文件被保存在/data/data/

<包名>/shared_prefs/目录下


a.如何获取SharePreferences对象


1.Context类的getSharePreferences()方法

该方法接收两个参数

第一个参数,是SharePreferences文件的名字,如果文件不存在,就会自动新建一个。SharePrefe

rences文件被保存在/data/data/<包名>/shared_prefs/目录下

第二个参数,代表操作模式,目前只剩下一个默认模式:MODE_PRIVATE,和直接传入0效果一样,表示

只有当前的应用程序,才可以对该SharePreferences文件进行读写。

2.Activity类的getPreferences()方法

总体上跟Context的getSharePreferences()方法很类似

该方法只接收一个参数

参数,代表操作模式,目前只剩下一个默认模式:MODE_PRIVATE,和直接传入0效果一样,表示只有

当前的应用程序,才可以对该SharePreferences文件进行读写。

该房啊会自动将当前活动的类名作为SharePreferences的文件名。

3.PreferenceManger类getDefaultSharedPreferences() 方法

该方法是一个静态方法

接收一个Context参数,可以将当前活动的对象传进去,活动是一个Context类型

会自动将当前应用程序的包名作为前缀,来命名SharePreferences文件

b.如何存储数据


  1. 调用SharePreferences类的edit()方法,获得SharePreferences.Editor对象

  2. 将数据添加到SharePreferences.Editor对象中;

    添加什么类型的数据就使用对应的方法:
    
    添加字符串,putString()
    
    添加整形,putInt()
    
  3. SharePreferences.Editor对象的apply()方法,提交数据。


获取 SharePreferences对象,并保存储数据:

 /**
     * 将数据存储到SharePreferences文件中
     */

    public void save() {
//        获取SharePreferences对象
        SharedPreferences preferences = getSharedPreferences("mySharePres", 0);
//        获取SharePreferences.Editor对象
        SharedPreferences.Editor editor = preferences.edit();
//        获取数据
        String str = edt_str.getText().toString();
        String str_num = edt_int.getText().toString();
//        只要有一个为空,就不保存
        if (TextUtils.isEmpty(str) || TextUtils.isEmpty(str_num)) {
            return;
        }
//        进行转换
        int num = Integer.parseInt(str_num);
//        保存数据,键值对
        editor.putInt("num",num) ;
        editor.putString("str",str) ;
//        提交数据
        editor.apply();

    }

c.如何恢复数据


  1. 获得SharePreferences

  2. 调用getXXX()方法,获取对应的数据

    该方法接收两个参数
    
    第一个参是键值对的键;
    
    第二个参数是默认值,就是没找到传入的键,就返回这个默认值
    

    /**
     * loading 方法
     */
    public void load(){
//        获取SharePres 对象
        SharedPreferences preferences = getSharedPreferences("mySharePres",0) ;
//        获取数据
        String str = preferences.getString("str","haha") ;
        int num = preferences.getInt("num",0) ;
//        设置数据
        edt_str.setText(str);
        edt_int.setText(num+"");
    }

可以使用SharedPreferences,做一个记住密码的功能

笔者做了一个demo,主要功能就是,用户输入用户名和密码以后,在点击登录按钮的时候,

先做个判断,判断是否选中记住密码,如果选中,则保存用户名和密码。

实质,无论是否选中记住密码,都会执行记住密码这一动作,唯一的差别,就是保存的密码,是密码还

是空串的区别。选中保存密码,就保存密码;没选中保存尼玛,就将密码保存为空串。

记住密码功能的完整代码:

/**
* 记住密码类
*/
public class Keep_name_paw extends AppCompatActivity implements View.OnClickListener {
    //        设置为全局变量,因为下面的多个方法中都会用到
//        获取SharePres对象
//        权限设置为append,
    SharedPreferences preferences ;
    //        获取Editor对象
    SharedPreferences.Editor editor ;


    EditText edt_name, edt_pass;
    CheckBox checkBox;
    Button btn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_keep_name_paw);

        preferences = getSharedPreferences("keepNamepass", MODE_APPEND);
        editor = preferences.edit();

        edt_name = (EditText) findViewById(R.id.edt_name);
        edt_pass = (EditText) findViewById(R.id.edt_pass);
        btn = (Button) findViewById(R.id.button);
        checkBox = (CheckBox) findViewById(R.id.checkBox);
        btn.setOnClickListener(this);

            /*
            对名字输入进行监听,如果这个用户名,之前选过记住密码,
            就自动为其补全密码
            使用addTextChangedListener()监听器
            需要复写三个方法,我们这里只用到文字发现改变的逻辑,
            因此,另外两个方法,为空就好了
             */
        edt_name.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
//            去SharePres文件中查找
                String key = edt_name.getText().toString() ;
                String value = load(key) ;
//                设置密码框
                edt_pass.setText(value);
            }

            @Override
            public void afterTextChanged(Editable s) {}
        }) ;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
//               读取数据
                String key = edt_name.getText().toString();
                String value = edt_pass.getText().toString();
//                判断是否选中记住密码
                if (!checkBox.isChecked()) {
//                    如果没选中
//                    就将之前保存的数据,的值,用空白替代
//                    这里我们,不能调用editor.clear()方法,
//                    这样整个SharePres文件就会被删除,其他用户的数据也被删除了

//                    就是用空白代替值value,进行保存
                    value = "";
                }
//               进行保存
                save(key, value);
                break;
        }
    }

    /**
     * 使用SharePreferences保存数据
     *
     * @param key   键
     * @param value 值
     */
    void save(String key, String value) {
//      保存数据
//      key就直接使用用户名,这样可以记住不同的账号和对应的密码
        editor.putString(key, value);
//        提交数据
        editor.apply();

    }

    /**
     * 加载数据
     */
    String load(String key) {
        String value = null;
//        读取数据,
//        第二个参数是默认值,如果没有对应的键,就返回默认值,这里是空串
        value = preferences.getString(key, "");
        return value;
    }
}

布局图片

Android持久化存储——(包含操作SQLite数据库)
(一.)利用文件存储
(二.)利用 SharePreferences 存储
(三)利用SQL数据库存储

<!--布局代码-->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_keep_name_paw"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_margin="10dp"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:text="账 号"
            android:textSize="25sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/textView2" />

        <EditText
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:maxLines="1"
            android:id="@+id/edt_name"
            android:layout_weight="1" />
    </LinearLayout>

    <LinearLayout
        android:layout_margin="10dp"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:text="密 码"
            android:textSize="25sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/textView3" />

        <EditText
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:maxLines="1"
            android:id="@+id/edt_pass"
            android:layout_weight="1" />
    </LinearLayout>

    <CheckBox
        android:text="记住密码"
        android:textColor="#abd123"
        android:textSize="20sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/checkBox" />

    <Button
        android:text="登 录"
        android:textSize="25sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="15dp"
        android:layout_gravity="right"
        android:layout_margin="10dp"
        android:id="@+id/button" />
</LinearLayout>

(三)利用SQL数据库存储

在前面介绍的两种方法中,存储的数据都是一些简单的数据;假如,我们需要保存一些具有关系型的数

据,前面的2种方法,将不再好用;对于关系型数据,首选项应该是数据库存储。

巧了,Android系统是内嵌sql数据库的。

这里将介绍两种操作数据库的方式。

1、使用SQLiteOpenHelper帮助类

Android为了我们,可以方便的操控数据库,提供了这个帮助类。感谢Android给与我们方便

a、什么是 SQLiteOpenHelper 帮助类

特点

1. 是一个抽象类,因此,我们需要自己创建一个帮助类去继承它;


2. 有两个抽象方法

创建数据库 onCreate( );

升级数据库 onUpgrade( ) ;


3. 有两个实例方法

返回SQLiteDatabase对象。

getReadableDatabase( ) ;

getWriteableDatabase( ) ;


共同点

这两个方法可以创建或者打开一个现有的数据库就是说,如果数据库已经存

在,就直接打开;不存在,就先新建一个数据库,再打开,并返回一个可对数

据库进行读写操作的对象。千万不要被字面意思骗了,以为Readable,就只能

进行读,不能对数据库进行写操作,两个方法,返回的对象,对数据库既可以进

行写操作,也可以进行读操作。


不同点

在数据库可以写入的情况下

两个方法返回的对象,都可以对数据库进行读写操作。

在数据库不可写入的时候

getReadableDatabase( ) 方法,将以只读方式打开数据库;

getWriteableDatabase( )方法将抛出异常;


b、如何创建自己的帮助类

道理我都懂,怎么创建自己的数据库帮助类?

上面已经提到,需要我们重写一个帮组类,继承自SQLiteOpenHelper类。

要想继承一个类,首先需要明确人家的构造器是什么样的?

SQLiteOpenHelper类一共有两个构造器,这里我们选择参数个数少的那一个,一个有四个参数。

第一个参数 Context

当前调用SQLiteOpenHelper的Activity对象的context

第二个参数 String

数据库的名字;创建数据库的名字,就是依据它;要加上后缀.db

第三个参数 SQLiteDatabase.CursorFactory

在查询数据的时候,可以返回一个自定义的Cursor,这里写null即可

第四个参数 int

表示当前数据库的版本号,用于对数据库的升级

c、利用自己的数据库帮助类,创建数据库

创建的数据库文件,保存在/data/data/<包名>/databases/目录下

步骤

1. 根据b中的构造器,创建自己数据库帮助类的实例

2. 再调用继承来的实例方法 getReadableDatabase( )、 getWriteableDatabase( )

3. 在调用继承来的实例方法,创建数据库时,我们复写的SQLiteOpenHelper类

的onCreate( ) 方法会被调用。通常在这里执行创建表的操作。


建立Book表的SQL语句:

很简单的sql语句

假如,你不太会sql语句,没关系,后面的LitePal操控数据库,将不需要写sql语句,完全是面向对象

的思想,在操控数据库。
create table Book (
    id integer primary key autoincrement ,
    author text,
    pages integer ,
    price real ) 

自定义的数据库帮助类

注意onCreate()方法
public class MySqliteOpenHelper extends SQLiteOpenHelper{

    String book_sql = "create table Book (
" +
            "	 id integer primary key autoincrement ,
" +
            "	 author text,
" +
            "	 pages integer ,
" +
            "	 price real,
"
            "	 name text )" ;

    Context context ;
    public MySqliteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        this.context = context ;
    }

    /**
     * 在调用实例方法的时候,如果数据库还未创建,这个方法就会被回调
     * 这个方法,仅在创建数据库的时候,得到调用
     * @param db
     */
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(book_sql);
        //这个Toast仅会弹出一次
        Toast.makeText(context,"数据库已创建",Toast.LENGTH_SHORT).show();
    }

    @Override
   public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)   {}
}

通过点击按钮创建数据库

在活动类中,对按钮设置监听器,在监听器里面创建数据库
public class Create_sql extends AppCompatActivity{

    private Button btn_createSql ;
    private MySqliteOpenHelper mySqliteOpenHelper ;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.create_sql_layout);
//        创建自己的数据库帮助类
        mySqliteOpenHelper = new MySqliteOpenHelper(this,"myDatabase.db",null,1) ;
//        获取按钮控件
        btn_createSql = (Button) findViewById(R.id.btn_createSql);
//        设置监听器
        btn_createSql.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//                获取可对数据库进行读写的对象
//                当我们第一次点击按钮的时候,会自动创建数据库
                mySqliteOpenHelper.getWritableDatabase() ;
            }
        });
    }
}

思考

这里有个问题,既然,我们把创建表的语句,写在onCreate()方法中,但是这个方法仅仅在创建数据

库的时候,会被调用一次。那么我们在以后,还想创建新的表怎么办呢?

答案:

刚刚有一个方法onUpgrade(),我们一直没用,从名字也可以看出,这个方法是升级数据库的。

既然,后续我们需要新增表,说明我们的数据库,需要升级,那么我们,就在这个升级数据库的方法

里,写上我们的逻辑。onUpgrade()方法,当程序发现,数据库版本号不一样的时候,就会调用

这个方法。因此,当我们需要升级数据库的时候,在创建数据库帮助类实例的时候,传入的版本号,

比之前大,就好了。


升级数据库(并不会将原有的数据库删除)

在库里面新增一张表,如果是对原有的表进行更新,需要先将原有的表删除,再新建。否则,程序会报错

因为,并不会将原有的数据库删除,因此,onCreate()方法,不会得到回调。

只会显式的回调onUpgrade()方法,但是我们可以在onUpgrade()方法中显式的调用这个方法。

sql语句

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

onUpgrade()方法

简单的写上新建表语句
  @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL(Category_sql);
    }

改变数据库的版本号

//        创建自己的数据库帮助类,将版本号从1变为2 。
        mySqliteOpenHelper = new MySqliteOpenHelper(this,"myDatabase.db",null,2) ;

总结:

我们可以看出来,我们只需要管理,创建数据库 onCreate( );升级数据库

onUpgrade( ) ;这两个方法。而对于getReadableDatabase( )

getWriteableDatabase( ) ;这两个方法,我们只需要用数据库帮助类实例去调

用即可。当我们调用的时候,如果没有数据库,它们就会回调onCreate()方

法,创建数据库;如果发现数据库版本号发现变化,就会回调onUpgrade( )方

法;否则,就简单的返回一个可对数据库进行读写的对象- - -SQLiteDatabase。

onUpgrade( )中的逻辑:

如果不是只新建一张表,而是需要要在原有表新添加一列呢?

这里需要注意,是否需要保存原有数据,如果不需要保存,直接删除,再新建

表;如果,需要保存原有数据,则将原来的表名,更名为一张临时表,再新建一

张表,这张表中有我们需要的新列,表名字跟原来的表一样。再将临时表中的数

据复制过来,最后,删除临时表。


在Android里,我们并不需要对sql语句如何熟悉!但是,我们却同样可以完成CRUD动作。这都要

归功于数据库帮助类实例方法返回的SQLiteDatabase对象


CRUD- — -添加数据


方法: SQLiteDatabase对象的 insert( )

 接受三个参数;

第一个参数是 表名

想往哪张表里面添加数据,就写哪张表的名字

第二个参数是 默认值,这里我们写null,即可

用于,我们没指定添加数据的情况下,给那些可为空的列,自动赋值为null

第三个参数是 ContentValues对象

该对象,提供了一系列put( )方法重载,利用put方法将数据保存到ContentValues对象中,

put( )方法接受两个参数

第一个参数是表中的列名;

第二个参数是列名对应的数据;

一个ContentValues对象,只能保存一条数据,在有多条数据的时候,每次装完一条数据的时候,需要

clear()一下。

添加数据的代码 :

这里仅给出关键代码,就是在按钮监听器中执行这一段添加数据的逻辑代码。
btn_insert.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//                添加数据,首先需要获取SQLiteDatabase对象
                SQLiteDatabase sqLiteDatabase = mySqliteOpenHelper.getReadableDatabase() ;
//                再创建ContentValues对象,保存数据
                ContentValues contentValues = new ContentValues() ;
//                添加数据
//                描述第一条数据
                contentValues.put("name","第一行代码");
                contentValues.put("price","59");
                contentValues.put("pages","570");
                contentValues.put("author","郭霖");
//                添加第一条数据
                sqLiteDatabase.insert("Book",null,contentValues) ;
//                清除第一条数据,再添加第二条数据
                contentValues.clear();

//                描述第二条数据
                contentValues.put("name","肥嘟嘟左卫门");
                contentValues.put("price","46");
                contentValues.put("author","野原新之助");
                contentValues.put("pages","2");
//                添加第二条数据
                sqLiteDatabase.insert("Book",null,contentValues) ;


            }
        });

查看数据库:

笔者刚刚一共点击了3次按钮,因此,生成6条数据;

Android持久化存储——(包含操作SQLite数据库)
(一.)利用文件存储
(二.)利用 SharePreferences 存储
(三)利用SQL数据库存储


CRUD- — -更新数据


方法: SQLiteDatabase对象的 update( )

 接受四个参数;

第一个参数是 表名

想往哪张表里面更新数据,就写哪张表的名字

第二个参数是 ContentValues对象

经过上面学习,我们已经知道,这个对象,就像是一个容器,保存,我们的数据;因此,这里,我们将

要更新的数据也放在这里面

第三、四个参数

用于约束更细某一行或者某几行中的数据,如不指定,默认更新所有行。

第三个参数是字符串,相当于where部分,这里写上你想跟新的字段,一般写上?占位符

第四个参数,是一个字符串数组,指明前面的?是谁。

更新数据代码:

//                更新数据,还是需要获取SQLiteDatabase对象
                SQLiteDatabase sqLiteDatabase = mySqliteOpenHelper.getReadableDatabase() ;
//                再创建ContentValues对象,保存数据
                ContentValues contentValues = new ContentValues() ;
//                写上要更新的数据
                contentValues.put("price",50);
//                将name是第一行代码 的数据的price更新为50
                sqLiteDatabase.update("Book",contentValues,"name = ? ",new String[]{"第一行代码"}) ;
//      清除之前contentValues的数据,否则下次更新,会将之前的数据也更新进来
                contentValues.clear();
                contentValues.put("pages",10);
//              将所有pages是130的,都更新为10
                sqLiteDatabase.update("Book",contentValues,"pages = ? ",new String[]{"130"}) ;

更新以后数据截图

笔者刚刚又点了2次添加数据按钮,因此数据多了4条

并且笔者,特意contentValues.clear();把这行注释了,

因此,我们可以发现之前pages=130的,不但pages被更新为10,就连price也被更新为50了

因此,验证了,笔者之前说的话:如果,没有清除之前contentValues的数据,下次更新,会将之前的

数据也更新进来

Android持久化存储——(包含操作SQLite数据库)
(一.)利用文件存储
(二.)利用 SharePreferences 存储
(三)利用SQL数据库存储


## CRUD- — -删除数据

----------

方法: SQLiteDatabase对象的 update( )

 接受四个参数;

第一个参数是 表名

想删除哪张表的数据,就写哪张表的名字

第二、三个参数

同样是用来删除哪一行的数据,不指定的话,就删除所有行。

删除第一行代码的数据

肥嘟嘟左卫门,是小新的书诶!不能删除。。委屈一下郭神
                SQLiteDatabase sqLiteDatabase = mySqliteOpenHelper.getReadableDatabase() ;
//            删除第一行代码数据的数据
                sqLiteDatabase.delete("Book","name=?",new String[]{"第一行代码"}) ;

效果图:

可以看到,仅剩下小新的书了。

Android持久化存储——(包含操作SQLite数据库)
(一.)利用文件存储
(二.)利用 SharePreferences 存储
(三)利用SQL数据库存储


## CRUD- — -查询数据

最重要的一种操作。

方法: SQLiteDatabase对象的 query( )

这个方法的重载非常复杂,最短的一个方法重载,也需要7个参数。

我们,重点看7个参数的重载方法。

但是,并不是每次查询都需要,写满7个参数。大多数情况下,只需要传入少数几个参数,就可以完成查

询操作。

参数

1. table - - - - 指定查询的表名;

2. columns - - - - 指定查询的列名;

3. selection - - - - 指定where的约束条件

4. selectionArgs - - - - 为where中的占位符提供具体的值

5.groupBy - - - - 指定需要group by 的列

6. having - - - - 对group by 的结果进行进一步的约束

7.orderBy - - - - 指定查询结果的排序方式


返回值

方法返回一个Cursor对象,查询到的所有数据都将从这个对象中取出。


获取 Cursor对象中的数据

1. moveToFirst() 先判断 Cursor对象中是否有数据,将数据的指针移到第一

行,有数据,就返回真,没数据就返回假;

2.moveToNext() 将数据指针移动到下一行,同样返回真(有数据)、假

(没有数据);跟迭代器用法类似。

3.获取一行中某个字段的值: 使用Cursor对象的getColumnIndex(列名);获取该列

在表中的索引,再调用Cursor对象的getXXX(索引)方法,即可获取到该列的数

据。

4.最后需要关闭Curson对象

代码:

//                查询数据
                SQLiteDatabase sqLiteDatabase = mySqliteOpenHelper.getReadableDatabase() ;
//      写入的参数,代表将整张表数据都查询出来
                Cursor cursor = sqLiteDatabase.query("Book",null,null,null,null,null,null);
//           将数据指针移动第一行
     if(cursor.moveToFirst()){
       do{
          int id = cursor.getInt(cursor.getColumnIndex("id")) ;
          int pages = cursor.getInt(cursor.getColumnIndex("pages")) ;
          String name = cursor.getString(cursor.getColumnIndex("name")) ;
          String  author = cursor.getString(cursor.getColumnIndex("author")) ;
          float price = cursor.getFloat(cursor.getColumnIndex("price")) ;

          Log.d("sql_query", id+" "+pages+" "+name+" "+author+" "+price);
         }while(cursor.moveToNext()) ;
      }

//     还需要关闭Cursor
       cursor.close(); 

查询图:

Android持久化存储——(包含操作SQLite数据库)
(一.)利用文件存储
(二.)利用 SharePreferences 存储
(三)利用SQL数据库存储


查询Book表中,id和name列的数据,其中id必须大于3

  Cursor cursor = sqLiteDatabase.query("Book",new String[]{"id","name"},"id>?",new String[]{"3"},null,null,null);

查询图

Android持久化存储——(包含操作SQLite数据库)
(一.)利用文件存储
(二.)利用 SharePreferences 存储
(三)利用SQL数据库存储