05. Android基础——数据存储相关

  1. Android系统提供了三种方式用于简单地实现数据持久化功能
    1. 文件存储
    2. SharedPreferences存储
    3. 数据库存储

文件存储

  1. 所有的数据都会原封不动的保存到文件当中,比较适合存储简单的文本数据或二进制数据

存储数据

  1. Context类中有一个openFileOutput()方法,用来存储数据,这个方法接受两个参数

    1. 第一个参数是文件名,在文件创建的时候使用的名字

      • 文件名不包括路径
      • 所有的文件默认都存储在/data/data/<package name>/files/这个目录下
    2. 第二个参数是文件的操作模式

      • MODE_PRIVATE
        • 默认操作模式
        • 当指定同样的文件名时,新写入的内容会覆盖原来的内容
      • MODE_APPEND
        • 如果文件存在了,就追加写入内容
        • 文件不存在就创建新的文件
    3. 这个方法返回的是一个FileOutputStream对象,可以通过Java流的方式将数据写入到文件中

    4. 例子

      public void save(String inputText){
          FileOutputStream out = null;
          BufferedWriter writer = null;
          try{
              out = openFileOutput("data",Context.MODE_PRIVATE);
              write = new BufferedWriter(new OutputStreamWrite(out));
              write.write(inputText);
          } catch(IOException e){
              e.printStackTrace();
          } finally{
              try{
                  if (writer != null){
                      writer.close()
                  }
              } catch(IOException e){
                  e.printStackTrace();
              }
          }
      }
      

读取数据

  1. 使用openFileInput()方法读取数据,这个方法只接收一个参数,就是要读取的文件名

  2. 系统会自动去默认的目录下加载要读取的文件,然后返回一个FIleInputStream对象,然后再通过Java流的方式操作

  3. 例子

    public String load(){
        FileInputStream对象 in = null;
        BufferedReader reader = null;
        StringBuilder content = new StringBuilder();
        try{
            // 获取一个FileInputStream对象
            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. Context类中的getSharedPreferences()方法

    1. 这个方法接收两个参数
    2. 参数1:用来指定SharedPreferences文件的名称,如果指定的文件不存在就创建一个(文件都存放在/data/data/<pacakagename>/shared_prefs/目录下)
    3. 参数2:用于指定操作模式,只有一种模式MODE_PRIVATE,也可以直接传入0
      1. 在Android4.2中被废弃的模式:MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE
      2. 在Android6.0中被废弃的模式:MODE_MULTI_PROCESS
  2. Activity类中的getSharedPreferences()方法

    1. 和上面的方法相似,但是只接收一个参数
    2. 参数:操作模式
    3. 使用这个方法的时候会自动将当前活动的类名作为SharedPreferences的文件名
  3. PreferenceManager类中的getDefaultSharedPreferences()方法

    1. 静态方法,接收一个Context参数,自动使用当前应用程序的包名作为前缀名来命名SharedPreferences文件
    2. 存储数据分为三步
      • 调用SharedPreferences对象的edit()方法来获取一个SharedPreferences.Editor对象
      • 向SharedPreferences.Editor对象中添加数据
      • 调用apply()方法将添加的数据提交即可
  4. 例子

    public class MainActivity extends AppCompatActivity{
        @Override
        protected void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Button saveData = (Button)findViewById(R.id.save_data);
            saveData.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    SharedPreferences.Editor editor = getSharedPreferences("data",MODE_PRIVATE).edit();
                    editor.putString("name","Tom");
                    editor.putInt("age",28);
                    editor.putBoolean("married",false);
                    editor.apply();
                }
            });
        }
    }
    
    • 通过getSharedPreferences()方法指定SharedPreferences的文件名叫data

从SharedPreferences读取数据

  1. SharedPreferences对象中提供了一系列的get方法来读取数据,get方法对应put方法(putString对应getString)

  2. 这些get方法接收两个参数

    1. 参数1:键,传入存储数据时使用的键
    2. 参数2:默认值,当传入的键找不到对应的值的时候以默认的值进行返回
  3. 例子

    public class MainActivity extends AppCompatActivity{
        @Override
        protected void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Button readData = (Button) findViewById(R.id.read_data);
            readData.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    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);
                }
            });
        }
    }
    

SQLite数据库

创建数据库

  1. 借助SQLiteOpenHelper类来操作数据库

  2. SQLiteOpenHelper类是一个抽象类,必须自己写一个类来继承它,自己写的类必须重写其中的onCreate()方法和onUpgrade()方法

  3. SQLiteOpenHelper类中的两个重要的方法getReadableDatabase()和getWritableDtatabase()

    1. 这两个方法都可以创建或打开一个数据库(数据库存在就打开,不存在就创建),返回返回一个可以对数据库进行读写操作的对象
    2. 当数据库不能写入的时候,getReadableDatabase()方法返回的对象只能以只读的方式打开数据库,getWritableDtatabase()方法会出现异常
  4. SQLiteOpenHelper类有两个构造方法,构造方法有四个参数

    1. 参数1:Context,必须有它才能操作数据库
    2. 参数2:数据库名字,创建数据库的时候使用这个名字
    3. 参数3:查询数据的时候返回一个自定义的Cursor,可以传入null
    4. 参数4:数据库的版本号
  5. 数据库文件存放在/data/data/<package_name>/databases/这个目录下

  6. 例子

    1. 创建一个MyDatabaseHelper类继承SQLiteOpenHelper类

      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, "创建成功", Toast.LENGTH_SHORT).show();
          }
      
          @Override
          public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
      
          }
      }
      
      • 定义一个类,然后在类中写一个创建数据库的语句
      • 重写onCreate()方法,在这个方法中调用刚才写的语句
    2. 然后创建数据库

      public class MainActivity extends AppCompatActivity{
          private MyDatabaseHelper dbHelper;
          @Override
          protected void onCreate(Bundle savedInstanceState){
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              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 view) {
                     dbHelper.getWritableDatabase();
                  }
              });
          }
      }
      

升级数据库

  1. 使用onUpgrade()方法来升级数据库

  2. 例子

    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 static final String CREATE_CATEGORY = "create table Category("
                + "id integer primary key autoincrement,"
                +"category name text,"
                +"category code integer)";
    
        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);
            db.execSQL(CREATE_CATEGORY);
            Toast.makeText(mContext, "创建成功", Toast.LENGTH_SHORT).show();
        }
    
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            
            // 当表Book和Category存在的时候就删除
            db.execSQL("drop table if exists Book");
            db.execSQL("drop table if exists Category");
            onCreate(db);
        }
    }
    
    
  3. 要执行onUpgrade()方法,只需要在SQLiteOpenHelper的构造方法中,修改第四个参数就可以

    public class MainActivity extends AppCompatActivity{
        private MyDatabaseHelper dbHelper;
        @Override
        protected void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // 因为之前第四个参数的值是1,这里只要比1大就行
            dbHelper = new MyDatabaseHelper(this,"BookStore.db",null,2);
            Button createDatabase = (Button) findViewById(R.id.create_database);
            createDatabase.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                   dbHelper.getWritableDatabase();
                }
            });
        }
    }
    

添加数据

  1. SQLiteDatabae中提供了一个insert()方法来添加数据

  2. insert(table_name,null,ContentValues)

    1. 参数1:表名
    2. 参数2:在未指定添加数据的情况下给某些可以为空的列自动赋值NULL,可以直接写null
    3. 参数3:ContentValues对象,这个对象提供了一系列的put()方法,将表中每个列名以及相应的待添加数据传入就行了
  3. 例子

    public class MainActivity extends AppCompatActivity{
    
        private MyDatabaseHelper dbHelper;
        @Override
        protected void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            dbHelper = new MyDatabaseHelper(this,"BookStore.db",null,1);
            Button addData = (Button) findViewById(R.id.add_data);
            addData.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    SQLiteDatabase db = dbHelper.getWritableDatabase();
                    ContentValues values = new ContentValues();
    
                    // 下面的代码用来组装一条要插入数据库中的数据
                    values.put("name","A Book");  // put()第一个参数是表中的列名,第二个是要插入的值
                    values.put("author","Jone Doe");
                    values.put("pages",444);
                    values.put("price",55.45);
    
                    // 将组装好的数据插入到数据库中
                    db.insert("Book",null,values);
                    values.clear();
                }
            });
        }
    }
    

更新数据

  1. SQLiteDatabae中提供了一个update()方法来添加数据

  2. update(table_name,ContentValues,args,args)

    1. 参数1:表名
    2. 参数2:ContentValues对象,更新的数据在这里完成组装
    3. 参数3和4用于约束更新的范围,是哪一行还是哪几行,不指定就默认更新所有行
  3. 例子

    public class MainActivity extends AppCompatActivity{
    
        private MyDatabaseHelper dbHelper;
        @Override
        protected void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            dbHelper = new MyDatabaseHelper(this,"BookStore.db",null,1);
            Button updateData = (Button) findViewById(R.id.update_data);
            updateData.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    SQLiteDatabase db = dbHelper.getWritableDatabase();
                    ContentValues values = new ContentValues();
                    
                    values.put("price",56.78);
                    
                    // 参数3相当于SQL语句中的where部分
                    // 这里表示更新所有name等于?的行,?在这里表示占位符,具体的值通过参数4提供
                    // 参数4提供了一个字符串数据,来给参数3中的占位符指定相应的内容
                    db.update("Book",values,"name=?",new String[]{"A Book"});
                }
            });
        }
    }
    

删除数据

  1. SQLiteDatabae中提供了一个delete()方法来添加数据

  2. delete(table_name,args,args)

    1. 参数1:表名
    2. 参数2和参数3:用于约束删除哪一行或者哪几行的数据,不指定就默认删除所有行
  3. 例子

    public class MainActivity extends AppCompatActivity{
    
        private MyDatabaseHelper dbHelper;
        @Override
        protected void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            dbHelper = new MyDatabaseHelper(this,"BookStore.db",null,1);
            Button deleteButton = (Button) findViewById(R.id.delete_data);
            deleteButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    SQLiteDatabase db = dbHelper.getWritableDatabase();
                    
                    // 这里表示删除页数超过300的数据
                    db.delete("Book","pages > ?",new String[]{"300"});
                }
            });
        }
    }
    

查询数据

  1. SQLiteDatabae中提供了一个query()方法来添加数据

  2. 调用query()方法之后会返回一个Cursor对象,查询到的数据都从这个对象中取出

  3. query()方法有7个参数

    1. 参数1:表名
    2. 参数2:指定去查询哪几列,不指定就默认查询所有列
    3. 参数3,参数4:用于约束查询某一行或某几行的数据,不指定就默认查询所有行的数据
    4. 参数5:用于指定需要去group by的列,不指定就表示不对查询结果进行group by的操作
    5. 参数6:用于对group by之后的数据进行进一步过滤,不指定就不进行过滤
    6. 参数7:指定查询结果的排序方式,不指定就表示使用默认的排序方式
  4. 例子

    public class MainActivity extends AppCompatActivity{
    
        private MyDatabaseHelper dbHelper;
        @Override
        protected void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            dbHelper = new MyDatabaseHelper(this,"BookStore.db",null,1);
            Button queryButton = (Button) findViewById(R.id.retrieve_data);
            queryButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    SQLiteDatabase db = dbHelper.getWritableDatabase();
    
                    // 查询表中所有的数据
                    Cursor cursor = db.query("book",null,null,null,null,null,null);
                    if (cursor.moveToFirst()){
                        do {
                            String name = cursor.getString(cursor.getColumnIndex("name"));
                            String author = cursor.getString(cursor.getColumnIndex("author"));
                        }while (cursor.moveToNext());
                    }
                    cursor.close();
                }
            });
        }
    }
    
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,634评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,951评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,427评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,770评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,835评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,799评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,768评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,544评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,979评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,271评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,427评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,121评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,756评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,375评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,579评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,410评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,315评论 2 352

推荐阅读更多精彩内容