保存在内存中的数据是瞬时数据,文件存储
分类:美高梅网上注册平台

一般在做一些面试题的时候,Android有几种数据存储方案这个问题是经常碰到的。在我们实际应用中,任何一个应用程序说白了都是在不停的和数据接触,比如我们通过QQ,微信聊天都是一个数据传输的过程。又比如我们逛新闻,逛微博,刷淘宝等也都是一个数据展示的过程。说实在点没有数据,所有的应用都是空架子。目前绝大多数数据都是由用户产生的,发评论发朋友圈的等等都是一个产生数据的过程。 因为我们知道垃圾回收机制,当程序关闭或其他原因导致数据被回收掉的时候,会有些数据被丢失,这些是瞬时数据,例如,在输入框输入一个数字,发送一个字符串等,一旦我们没有再需要的时候就会丢失。但是有些数据需要持久的保存不想被回收掉,例如朋友圈的动态和评论,微博留言等。这就需要保持关键新的数据不丢失。

.1. **Android系统中的三种存储方式 **

  • 瞬时数据:指那些存储在内存当中,有可能会因为程序广播或其他原因导致内存被回收而丢失的数据。
  • 数据持久化:指将那些内存中的瞬时数据保存到存储设备中,保证即使在手机或电脑关机的情况下,这些数据仍然不丢失。

数据持久化处理是将内存中的数据能够被保存在特定的存储空间中,保证数据在程序关闭和异常情况下不会被丢失。Android 系统提供了5种方式来保存数据:1.文件存储2.SharePreference存储3.数据库存储4.ContentProvider存储5.网络存储

  • 文件存储
  • SharedPreference存储
  • SQLite存储

  保存在内存中的数据是瞬时数据,保存在手机设备中的数据是处于持久状态的,持久化技术则是提供了一种机制可以让数据在瞬时状态和持久状态之间进行切换。

文件存储是Android中最基本的一种数据存储方法。它通过文件的方式将数据不做任何处理的存储进文件中,因此适合存储一些简单的文本数据或者二进制数据。当然也不是不适合存储复杂的文本数据,只是需要定义一套自己的格式规范,方便之后将数据从文件中重新解析出来。


1、持久化技术有哪些  

  Android系统中主要提供了三种方式用于简单地实现数据持久化功能:

  1. 文件存储:是Android中最基本的一种数据存储方式。不对存储内容做任何的格式化处理,所有数据都是原封不动地保存到文件中。因此,这种方式比较适合存储一些文本数据或二进制数据。如果你想使用文件存储的方式来保存比较复杂的文本数据,则需要自己定义一套格式规范,这样方便之后将数据从文件中重新解析出来。
  2. SharedPreferences存储:使用键值对的方式存储数据。也就是说当保存一条数据时,需要给这条数据提供一个对应的键,这样在读取数据时就可以通过这个键把相应的值取出来。此外,SharedPreference还支持多种不同数据类型的存储。
  3. 数据库存储:SQLite是一款轻量级的关系型数据库,运算速度快,占用资源少,通常只需要几百k就可以了。不仅支持标准的SQL语法,还遵循了数据库的ACID事务。

  此外,我们还可以通过将数据存储到SD卡中。不过使用上述三种方式会更加简单一些,而且也更加安全。

文件IO流的存取提供了FileOutputStram()和FileInputStream()这两个方法来存储和取出文件中的数据。openFileOutput()这个方法可以用于将数据存储到指定为文件中。openFileOutput(String name , int mode)这个方法第一个参数用于指定文件名,第二个参数指定打开文件的模式。具体有:

.2. 文件存储

2、文件存储

  • 将数据保存到文件:利用Context类中的openFileOutput(String fileName, int mode)方法可以将数据存储到指定的文件中,该方法返回一个FileOutputStream对象,得到该对象之后,使用Java流的方式将内容写入文件中。该方法接收两个参数:
    • 第一个参数是文件名,在文件创建的时候使用的就是这个文件名,注意,这里指定的文件名不可以包含路径,因为所有的文件都默认存储到/data/data/<packageName>/files/目录下的。
    • 第二个参数是文件的操作模式,主要有两种可选模式,MODE_PRIVATE和MODE_APPEND,其中MODE_PRIVATE是默认操作模式,表示当指定同样文件名的时候,所写入的内容会覆盖原文件中的内容,而MODE_APPEND则表示如果该文件已经存在,则将新内容追加到原文件内容的后面。此外,还有两种可选模式,MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE,分别表示允许其他应用程序对我们程序中的文件进行读写操作,不过由于这两种操作模式过于危险,很容易引起安全性漏洞,已经被废弃。
  • 从文件中读取数据:同样利用Context类中的openFileInput(String fileName)方法可以将数据存储到指定的文件中,该方法返回一个FileInputStream对象,得到该对象之后,使用Java流的方式将文件中的内容读出。该方法只接收一个参数,就是文件名,然后系统会自动从/data/data/<packageName>/files/目录下去加载这个文件,并返回一个FileInputStream对象。 

  文件存储的方式并不适用于保存一些较为复杂的文本数据。 

  1. MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中。可以使用Context. MODE_APPEND 。
  2. MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。
  3. MODE_WORLD_READABLE:表示当前文件可以被其他应用读取;
  4. MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入。(后面两种在Android4.2版本中被废弃了)具体实现将数据存储的步骤:1.首先新建一个layout文件activity_file_save.xml.这个页面就两个控件,一个输入框EditText,一个保存按钮。

文件存储又可分为内部存储(Internal storage)和外部存储(External storage).

3、SharedPreferences存储

  • 通过SharedPreferences存储数据:SharedPreference存储的数据都以xml格式存储,并且都美高梅网上注册平台 ,自动保存到/data/data/<packageName>/shared_prefs/目录下。主要步骤如下:
  1. 首先需要获取到SharedPreferences对象。Android中主要提供了三种方法用于得到SharedPreferences对象:
    1. Context类中的getSharedPreferences(String name, int mode)方法:此方法接收两个参数,第一个参数用于指定SharedPreference文件的名称,如果指定的文件不存在则会创建一个。第二个参数指定操作模式,主要有两种模式可选:MODE_PRIVATEMODE_MULTI_PROCESS,MODE_PRIVATE仍然是默认选项,表示只有当前应用程序可以对这个SharedPreference文件进行读写;MODE_MULTI_PROCESS则一般是用于会有多个进程对同一个SharedPreferences进行读写的情况。类似地,MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE也已经被废弃使用了。
    2. Activity类中的getPreferences(int mode)方法:这个方法和第一个很相似,它只接收一个参数,就是操作模式。因为使用该方法会自动将当前活动的类名作为SharedPreferences文件的文件名。
    3. PreferenceManager类中的getDefaultSharedPreferences(Context context)方法:这是一个静态方法,它接收一个context参数,并自动当前应用程序的包名作为前缀名来命名SharedPreferences文件。
  2. 得到SharedPreferences对象之后,我们就可以开始往SharedPreference文件中写数据了,需要按照以下三个步骤来进行:
    1. 调用SharedPreferences对象的edit()方法获取一个SharedPreferences.Editor对象editor
    2. 向上一步获取的SharedPreferences.Editor对象中添加数据,比如添加一个boolean型数据就使用editor.putBoolean(String key, boolean value)方法,添加字符串就使用editor.putString(String key, String value)方法,以此类推。
    3. 最后所有数据添加完成之后调用editor.commit()方法将调价的数据进行提交。如果不进行commit(),则之前添加的数据将不会修改到文件中去
  • 从SharedPreferences中读取数据:从SharedPreferences类中我们可以看到有一系列get方法,显然,我们从SharedPreferences中读取数据是通过这些get方法来完成的。值得注意的是:这些get方法均接收两个参数,第一个是String类型的key,传入存储数据时使用的键就可以得到相应的值,第二个则是我们参数是默认值,即表示当我们传入的键找不到对应的值时,会以什么样的默认值进行返回。具体步骤如下:
    1. 获取SharedPreferences对象
    2. 调用SharedPreferences对象的get方法获取数据,例如读取boolean类型数据就使用getBoolean(String key, boolean defValue) 方法进行获取

1.内部存储

4、SQLite数据库存储

  • 创建SQLiteOpenHelper对象:Android为了让我们能够更加方便地管理数据库,专门提供了一个SQLiteOpenHelper帮助类,借助这个类我们可以非常简单地对数据库进行创建和升级了。

        1. SQLiteOpenHelper是一个抽象类,使用它时我们自己的类必须实现其两个抽象方法onCreate(SQLiteDatabase db)方法onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)方法,分别实现创建和升级数据库的逻辑。
           1 public class CoolWeatherOpenHelper extends SQLiteOpenHelper {
           2     
           3     /**
           4      *  Province表建表语句
           5      */
           6     public static final String CREATE_PROVINCE = "create table Province ("
           7                 + "id integer primary key autoincrement, " 
           8                 + "province_name text, "
           9                 + "province_code text)";
          10     /**
          11      *  City表建表语句
          12      */
          13     public static final String CREATE_CITY = "create table City ("
          14                 + "id integer primary key autoincrement, " 
          15                 + "city_name text, " 
          16                 + "city_code text, " 
          17                 + "province_id integer)";
          18     /**
          19      *  County表建表语句
          20      */
          21     public static final String CREATE_COUNTY = "create table County ("
          22                 + "id integer primary key autoincrement, " 
          23                 + "county_name text, " 
          24                 + "county_code text, " 
          25                 + "city_id integer)";
          26 
          27     public CoolWeatherOpenHelper(Context context, String name, CursorFactory factory,
          28             int version) {
          29         super(context, name, factory, version);
          30     }
          31 
          32     @Override
          33     public void onCreate(SQLiteDatabase db) {
          34         db.execSQL(CREATE_PROVINCE);  // 创建Province表
          35         db.execSQL(CREATE_CITY);  // 创建City表
          36         db.execSQL(CREATE_COUNTY);  // 创建County表
          37     }
          38 
          39     @Override
          40     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
          41         //调用db.execSQL()方法执行数据库的更新和升级,
          42         
          43         onCreate(db) ;  //重新创建数据库
          44     }
          45 }
          
    1. 然后利用其构造方法public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version)来创建对象SQLiteOpenHelper对象

      • 其中第一个参数是context,必须要有它才能对数据库进行操作;
      • 第二个参数是数据库名,创建数据库时使用的就是这里指定的名称;
      • 第三个参数是允许我们在查询数据时候返回一个自定义的Cursor,一般都传入null;
      • 第四个参数表示当前数据库的版本号,可用于对数据库进行升级操作。当前版本号和之前的版本号不同时,onUpgrade()方法就会得到执行
  • 创建数据库:得到SQLiteOpenHelper对象之后,我们可以利用其public SQLiteDatabase getReadableDatabase() 方法或public SQLiteDatabase getWritableDatabase()方法来创建我们的数据库,并且获得了一个数据库对象,后面我们可以利用这个数据库对象对我们创建的数据库进行各种增删查改操作。

     1 public class CoolWeatherDB {
     2 
     3     // 数据库名
     4     public static final String DB_NAME = "cool_weather" ;
     6     // 数据库版本
     7     public static final int VERSION = 1;
     8 
     9     private static CoolWeatherDB coolWeatherDB;
    10 
    11     private SQLiteDatabase db;
    12 
    13     // 将构造方法私有化
    14     private CoolWeatherDB(Context context) {
    15         // 创建帮助类对象
    16         CoolWeatherOpenHelper dbHelper = new CoolWeatherOpenHelper(context,DB_NAME, null, VERSION);
    18          // 创建数据库
    19         db = dbHelper.getWritableDatabase();
    20     }
    21 
    22     // 获取CoolWeatherDB的实例。
    23     public synchronized static CoolWeatherDB getInstance(Context context) {
    24         if (coolWeatherDB == null) {
    25             coolWeatherDB = new CoolWeatherDB(context);
    26         }
    27         return coolWeatherDB;
    28     }    
    29 }    
    

 

  • 对数据库的操作CRUD,即增删查改。这里我们利用上面得到的SQLiteDatabase数据库对象提供的各种方法来进行相关的操作。

    • Create:创建、添加。利用SQLiteDatabase数据库对象insert(String table, String nullColumnHack, ContentValues values)方法实现添加数据:第一个参数是数据库中的表名,第二个一般直接传入null即可,第三个参数是一个ContentValues对象,它提供了一系列的put()方法的重载,用于向ContentValues对象中添加数据,只需将表中的每个列名以及相应的待添加的数据传入即可。ContentValues的底层是一个HashMap集合,键即为对应表中的各列的名称,值是我们传入的数据。

       1 /**
       2  * 将County实例存储到数据库。
       3  */
       4 public void saveCounty(County county) {
       5     if (county != null) {
       6         ContentValues values = new ContentValues();
       7         values.put("county_name", county.getCountyName());
       8         values.put("county_code", county.getCountyCode());
       9         values.put("city_id", county.getCityId());
      10         db.insert("County", null, values);
      11     }
      12 }
      
    • Update:更新。利用SQLiteDatabase数据库对象提供的update(String table, ContentValues values, String whereClause, String[] whereArgs)方法实现更新数据库中的数据。第一个参数就是表名,第二个是要更新的数据组装成的ContentValues对象,第三个和第四个参数用于约束更新某一行或某几行的数据,不指定的话是默认更新所有行。

       1 /**
       2  * 对存储到数据库的County实例进行更新。
       3  */
       4 public void updateCounty(County county) {
       5     if (county != null) {
       6         ContentValues values = new ContentValues();
       7         values.put("county_name", "beijing");
       8         values.put("county_code", "001");
       9         db.update("County", values, "city_id = ?", new String [] {"010201"}) ;
      10     }
      11 }
      

      **第三个参数对应的是SQL语句中的where部分,表示去更新所有city_id

      ?的行,而?是一个占位符,可以通过第四个参数提供的一个字符串组为第三个参数中的每个站位符指定相应的内容。**

    • Delete:删除。利用SQLiteDatabase数据库对象提供的delete(String table, String whereClause, String[] whereArgs)方法实现删除数据库中的数据。各项参数前面都已经介绍过,就不一一介绍了。

       1 /**
       2  * 删除存储到数据库中的某些County实例。
       3  */
       4 public void deleteCounty(County county) {
       5  6         db.delete("County", "county_name = ? ", new String [] {"beijing"}) ; 7 }
      
    • Retrieve:查询。利用SQLiteDatabase数据库对象提供的public Cursor query(String table, String[] columns, String selection,String[] selectionArgs, String groupBy, String having,String orderBy)方法实现查询数据库中的数据。该方法返回一个Cursor游标对象,查询到的所有数据都将从这个对象中取出。

      query()方法参数 对应的SQL部分 描述
      table from table_name 指定查询表名
      columns select column1, column2 指定查询列名
      selection where column = value 指定where约束条件
      selectionArgs ---- 为where中的占位符提供具体的值
      groupBy group by column 指定需要group by的列
      having having column = value 对group by的结果进行进一步的约束
      orderBy order by column1, column2 指定查询结果的排序方式
       1 /**
       2  * 从数据库读取某城市下所有的县信息。
       3  */
       4 public List<County> loadCounties(int cityId) {
       5     List<County> list = new ArrayList<County>();
       6     Cursor cursor = db.query("County", null, "city_id = ?",
       7             new String[] { String.valueOf(cityId) }, null, null, null);
       8     if (cursor.moveToFirst()) {
       9         do {
      10             County county = new County();
      11             county.setId(cursor.getInt(cursor.getColumnIndex("id")));
      12             county.setCountyName(cursor.getString(cursor
      13                     .getColumnIndex("county_name")));
      14             county.setCountyCode(cursor.getString(cursor
      15                     .getColumnIndex("county_code")));
      16             county.setCityId(cityId);
      17             list.add(county);
      18         } while (cursor.moveToNext());
      19     }
      20     return list;
      21 }
      
  • 对数据的操作还可以直接使用SQL来操作数据库

     1 public void operateSQL(){
     2     //插入
     3     db.execSQL("insert into Country (country_name, country_code, city_id) values (?,?,?)",new String [] {"beijing","001","111"});
     4     //更新
     5     db.execSQL("update Country set country_name = ? where country_code = ?", new String [] {"beijing","002"});
     6     //删除
     7     db.execSQL("delete from Country where contry_code = ?", new String [] {"002"});
     8     //查询,注意:查询是用的rawQuery()方法,不再是execSQL()方法
     9     db.rawQuery("select * from Country", null) ;    
    10 }
    
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:andro android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <EditText android: android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="写点什么呗"/> <Button android: android:layout_width="match_parent" android:layout_height="50dp" android:text="保存数据"/></LinearLayout>
  • 总是可用的,程序默认将文件保存在这里
  • 当程序被卸载时,保存在这里的文件是默认全部被移除的

5、数据库的事务特性

  •  数据库的事务特性就是 ACID.
    1. Atomicity:原子性
    2. Consistancy:一致性
    3. Isolation:隔离性
    4. Durabolity:持久性
  • SQLite是支持事务特性的,事务特性可以保证让某一系列的操作要么全部完成,要么一个都不完成。其标准用法是利用SQLiteDatabase数据库对象提供的public void beginTransaction()方法和public void endTransaction()方法进行开启和结束一个事务,然后该事物中的所有关于数据库的操作就都在开启和结束中间完成。此外, public void setTransactionSuccessful()方法表示事务已经执行成功。

     1 public void operateSQL() {
     2     db.beginTransaction() ;
     3     try {
     4         // 插入
     5         db.execSQL("insert into Country (country_name, country_code, city_id) values (?,?,?)",
     6                 new String[] { "beijing", "001", "111" });
     7         // 更新
     8         db.execSQL("update Country set country_name = ? where country_code = ?", new String[] { "beijing", "002" });
     9         // 删除
    10         db.execSQL("delete from Country where contry_code = ?", new String[] { "002" });
    11         // 查询,注意:查询是用的rawQuery()方法,不再是execSQL()方法
    12         db.rawQuery("select * from Country", null) ;
    13         //如果在endTransaction()执行之前没有执行setTransactionSuccessful()方法的话表明事务执行失败,
    14         //所以所有操作一条都不完成
    15         db.setTransactionSuccessful() ;
    16     } catch (Exception e) {
    17         // TODO: handle exception
    18     }finally{
    19         db.endTransaction() ;
    20     }    
    21 }
    

     如果在endTransaction()执行之前没有执行setTransactionSuccessful()方法的话表明事务执行失败,所以所有操作一条都不完成。

 

2.新建一个Activity,处理保存数据的逻辑。通过调用openFileOutPut()的方法返回一个FileOutputStream对象。得到这个对象之后就可以使用Java保存文件的方法将数据写入到文件中。这里生成一个data文件保存文件中。代码如下:

2.外部存储

 private void save(String inputtext) { FileOutputStream outputStream = null; BufferedWriter bufferedWriter = null; try { outputStream = openFileOutput("data", Context.MODE_PRIVATE); bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream)); bufferedWriter.write(inputtext); Toast.makeText(FileSaveActivity.this, "保存数据成功"+inputtext, Toast.LENGTH_SHORT).show(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if(bufferedWriter!=null){ try { bufferedWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } }
  • 保存的文件可以随时读取,并且所有程序都可以获得这个文件的访问权
  • 当程序被卸载时,系统会移除这些文件,但是如果你在getExternalFileDir() 方法获得目录下保存文件的话,它将不会被移除

3.运行代码,在模拟器查看保存的数据。点击Android Studio 导航栏的Tools->Android->Android Device Monitor -> File Explorer,在这里找到data/data/com.demo.filesavedemo/files/目录 查看模拟器的数据。

3.两种方法的比较

美高梅网上注册平台 1Android 工具列表

  • 如果不想要文件被用户或者其他的app访问,那么内部存储是一个不错的选择
  • 如果是保存音乐,图片或者视屏类的文件,我们通常不希望应用程序被卸载时文件也被移除,所以最好选用外部存储的方式

Android7.0的模拟器有点小bug,选择6.0的好了。

4.使用内部存储 存储和读取文件

美高梅网上注册平台 2生成data文件

Context类提供了一个openFileOutput()方法,用于将数据存储到指定文件中,这个方法接受两个参数,第一个参数是文件名,第二个是文件的操作模式,有MODE_PRIVATE和MODE_APPEND两种方式,MODE_PRIVATE是系统默认的操作方式,当有相同文件名的文件时,这种方式会覆盖原文件,MODE_APPEND表示当文件存在时,追加内容,不存在则创建文件,这个方法返回一个FileOutputStream对象。

点击左边这个按钮,导出文件到电脑上:

Context 类还提供了一个openFileInput()方法,用于从文件中读取数据,这个方法只接收一个参数,即要读取的文件名,返回一个FileInputStream对象,得到这个对象后,可以通过Java流的方式获得数据。

美高梅网上注册平台 3导出导入按钮

public void save(View view) {

        FileOutputStream out  = null;
        BufferedWriter writer = null;
        String data = editText.getText().toString();
        try{
            out = openFileOutput("data",MODE_PRIVATE);
            writer = new BufferedWriter(new OutputStreamWriter(out));
            writer.write(data);
        }catch (IOException e){
            e.printStackTrace();
        } finally {
            if (writer != null){
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

 public void load(View view) {

        FileInputStream in = null;
        BufferedReader reader = null;
        StringBuilder builder = new StringBuilder();

        try {
            in = openFileInput("data");
            reader = new BufferedReader(new InputStreamReader(in));
            String line = "";
            while((line = reader.readLine())!=null){
                builder.append(line);
            }
        }catch (IOException e){

        } finally {
            if (reader !=null){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        editText.setText(builder.toString());
    }

输入qwert 保存,输入结果:

Tips:

美高梅网上注册平台 4输出结果

为了提升保存效率以及防止引起IOException异常,可以通过getFreeSpace()或者getTotalSpace()查看当前是否有足够的内存去保存文件。

这就证实了 输入的EditText的内容被成功保存到文件中了。

这种方式保存文件,文件默认保存在 /data/data/<package name>/files/目录下,可以借助DDMS下的File Explorer找到该文件。

类似于数据存储到文件中,Context类还提供了一个openFileInput()的方法,用于从文件中读取数据这个相比较openFileOutput()简单一些,只要读取文件名这个参数就可以了。系统会自动读取data/data/com.demo.filesavedemo/files/目录这个文件,并返回一个FileInputStream对象。得到这个对象之后就可以使用Java读取文件数据的方法读取文件中的数据

5.使用外部存储保存文件

 private String load(){ FileInputStream inputStream=null; BufferedReader bufferedReader=null; StringBuilder content=new StringBuilder(); try { inputStream = openFileInput; bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String line=" "; try { while ((line=bufferedReader.readLine{ content.append; } } catch (IOException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { e.printStackTrace(); }finally { if(bufferedReader!=null){ try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } } return content.toString(); }

通过getExternalStorageState()方法查询外部设备是否可用,当返回值为MEDIA_MOUNTED时,才可以读取和写入文件。

最后将文件存储输入和输出合并完整代码:1.activity_file_save.xml

.3.SharedPreferences存储

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:andro android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <EditText android: android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="写点什么呗"/> <Button android: android:layout_width="match_parent" android:layout_height="50dp" android:text="保存数据"/> <Button android: android:layout_width="match_parent" android:layout_height="50dp" android:text="读取数据"/> <TextView android: android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp" android:textSize="15sp" /></LinearLayout>
  • getSharedPreferences(String fileName, int mode)
    第一个参数为文件名称,第二个参数为操作模式,有MODE_PRIVATE 和MODE_MULTI_PROCESS两种。MODE_PRIVATE 仍然是系统默认的选择,和传入0效果相同,表示只有当前应用才可以对这个SharedPreferences文件进行读取。MODE_MULTI_PROCESS一般是用于有多个进程对同一个SharedPreferences进行读写的情况。
    这种方法定义的文件,你可以通过文件名在app任何一个Context中访问。

  • getPreferences(int mode)
    这种方式只接收一个参数,也即操作模式,使用这个方式将默认当前活动的类名为SharePreferences文件的名称。这种方式定义的文件默认属于这个Activity,不需要提供文件名称。

  • getDefaultSharedPreferences(Context context)
    这个方法是PreferenceManager类中的一个静态方法,接受一个Context参数,并自动使用当前应用程序的包名作为前缀命名SharedPreferences文件。

2.FileSaveActivity.java

获取到SharedPreferences对象后,就可以开始向SharedPreferences文件存储数据了,一般可分为三步:

ublic class FileSaveActivity extends AppCompatActivity { private static final String TAG = "FileSaveActivity"; private EditText editText; private Button btn_load_data,btn_save_data; private TextView tv_txt_load_data; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_file_save); editText =  findViewById(R.id.et_txt_content); tv_txt_load_data=  findViewById(R.id.tv_txt_load_data); btn_save_data=  findViewById(R.id.btn_save_data); btn_load_data=  findViewById(R.id.btn_load_data); btn_save_data.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String inputtext=editText.getText().toString(); save(inputtext); } }); btn_load_data.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String inputText=load(); Log.e(TAG, "onClick: "+inputText ); if(!TextUtils.isEmpty(inputText)){ tv_txt_load_data.setText(inputText); } Toast.makeText(FileSaveActivity.this, "读取数据成功="+inputText, Toast.LENGTH_SHORT).show; } //保存数据到文件中 private void save(String inputtext) { FileOutputStream outputStream = null; BufferedWriter bufferedWriter = null; try { outputStream = openFileOutput("data", Context.MODE_PRIVATE); bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream)); bufferedWriter.write(inputtext); Toast.makeText(FileSaveActivity.this, "保存数据成功"+inputtext, Toast.LENGTH_SHORT).show(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if(bufferedWriter!=null){ try { bufferedWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } } //读取文件中的数据 private String load(){ FileInputStream inputStream=null; BufferedReader bufferedReader=null; StringBuilder content=new StringBuilder(); try { inputStream = openFileInput; bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String line=" "; try { while ((line=bufferedReader.readLine{ content.append; } } catch (IOException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { e.printStackTrace(); }finally { if(bufferedReader!=null){ try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } } return content.toString(); }}
  1. 调用SharedPreferences的edit()方法,获取一个SharedPreferences.Editor对象。
  2. 向SharedPreferences.Editor对象中添加数据。
  3. 调用commit()方法提交数据。

所用的核心及技术就是openFileInput()和openFileOutput()方法,之后就是Java的各种读写流来进行读写操作。但是这种存储方式不适合保存复杂的文本数据。

与文件存储不同的是,SharePreferences存储是通过键值对来进行存储,在存储数据的时候,需要给数据提供对应的键,然后通过键来寻找相对应的值。而且SharePreferences支持多种不同的数据类型来进行存储,存取的过程中,数据的类型不会发生改变。

public void save(View view){
        SharedPreferences sharedPreferences = getSharedPreferences("data",MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();

        editor.putString("name","value");
        editor.putInt("age",20);
        editor.putBoolean("alive",true);

        editor.commit();
    }
}


public void load(View view){
        SharedPreferences reader = getSharedPreferences("data",MODE_PRIVATE);

        String name = reader.getString("name", ""); //第二个参数为默认值
        int age = reader.getInt("age",0);
        Boolean alive = reader.getBoolean("alive",false);
    }

实现SharedPreferences存储的步骤如下: 一、根据Context获取SharedPreferences对象 二、利用edit()方法获取Editor对象。 三、通过Editor对象存储key-value键值对数据。 四、通过commit()方法提交数据。示例代码:

.4.SQLite数据库存储

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_file_share_preference); Button button=  findViewById(R.id.btn_share_save); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { SharedPreferences.Editor editor=getSharedPreferences("data",MODE_PRIVATE).edit(); editor.putString("name","小强"); editor.putInt; editor.putBoolean("married",false); editor.apply(); Toast.makeText(FileSharePreferenceActivity.this, "保存数据成功", Toast.LENGTH_SHORT).show; }

为了方便的管理数据库,Android系统专门提供了一个抽象帮助类SQLiteOpenHelper,借助这个类可以对数据库进行创建和升级。SQLiteOpenHelper是抽象类,这意味着我们不能对它使用new方法,因此我们必须自定义一个类去继承他,并实现内部的抽象方法。

设置点击按钮,保存数据到data/data/com.demo.filesavedemo/shared_prefs/目录。查看的方法和上面的一样。生成了一个xml的文件

SQLiteOpenHelper内部包含两个抽象方法onCreate()和onUpgrade()方法,顾名思义,一个用来创建数据库,一个用来升级数据库。

美高梅网上注册平台 5SharedPreferences存储

SQLiteOpenHelper还有两个重要的实例方法 :

这里补充一下Android中主要提供了3种方法去得到SharedPreferences对象1.Context类中的getSharedPreferences()方法。这个方法接收两个参数,第一个参数是指定存放SharedPreferences文件的名称。如果指定的文件不存在,则会创建一个,SharedPreferences文件的存放目录为/data/data/<包名>/shared_prefs/目录,第二个参数用于指定操作模式。目前只有MODE_PRIVATE这一种模式可选,它是默认的操作模式,和直接传入数字0是一样的效果,表示只有当前的应用程序才可以对这个SharedPreferences文件进行存储。其他的操作模式均已废弃。MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE,在Android4.2版本被废弃了,MODE_MULTI_PROCESS是在6.0被废弃。2.Activity类中的getPreference()方法。这个方法与getSharedPreferences()方法很像,只是它只接受一个操作模式参数,使用这个方法会自动将当前活动的类名作为SharedPreferences的文件名。3.PreferenceManager类中的getDefaultSharedPreferences()方法。这是个静态方法,它接收一个Context参数,自动使用当前包名作为前缀来明明SharedPreferences文件。得到SharedPreferences对象之后,就可以开始存储数据了。

  1. getReadableDatabase() : 创建或者打开一个现有的数据库,如果数据库不可写入,将以只读方式打开。
  2. getWritableDatabase() : 创建或者打开一个现有的数据库,如果数据库不可写入,将会出现异常。

SharedPreferences的存储数据非常的简单,读取数据其实更加的简单。SharedPreferences提供了一系列的get()方法来对应存储的put()方法。但是与存储不同的是,提取的方法有两个参数,第一个参数是对应的字符类型,第二个是默认值,当传入的键找不到对应的值的时候会以什么样的默认值进行返回。1.修改activity_file_share_preference.xml文件

使用SQLite数据库存储文件通常需要三步 :

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:andro android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android: android:layout_width="match_parent" android:layout_height="50dp" android:text="SharePreference存储"/> <Button android: android:layout_width="match_parent" android:layout_height="50dp" android:text="SharePreference读取"/></LinearLayout>
  1. 自定义类继承SQLiteHelper并实现其内部抽象方法。
  2. 利用getWritableDatabase() 或者 getReadableDatabase() 获得操作对象。
  3. 进行C(Create) R(Retrieve) U(Update) D(Delete)操作。

2.修改FileSharePreferenceActivity.java文件

具体实现如下所示:

public class FileSharePreferenceActivity extends AppCompatActivity { private static final String TAG = "FileSharePreferenceActi"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_file_share_preference); Button button=  findViewById(R.id.btn_share_save); Button button2=  findViewById(R.id.btn_share_load); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { saveDate; button2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { loadDate; } public void saveDate(){ SharedPreferences.Editor editor=getSharedPreferences("data",MODE_PRIVATE).edit(); editor.putString("name","小强"); editor.putInt; editor.putBoolean("married",false); editor.apply(); Toast.makeText(FileSharePreferenceActivity.this, "保存数据成功", Toast.LENGTH_SHORT).show(); } public void loadDate(){ SharedPreferences spf=getSharedPreferences("data",MODE_PRIVATE); String name= spf.getString("name","");//字符串默认为空 boolean married= spf.getBoolean("married",false); int age= spf.getInt; Log.i(TAG, "loadDate: name="+name); Log.i(TAG, "loadDate: married="+married); Log.i(TAG, "loadDate: age="+age); }}

根据Google开发者文档的建议,我们最好定义一个合约类去管理我们所有的建表语句,并将它们设置为全局变量,以便Activity统一访问。

先将数据存储到shared_prefs目录下的文件,再将文件里的数据读取出来

public final class TableManager {

    public TableManager(){}

    public static abstract  class PERSON_TABLE{
        public static final String ID = "id";
        public static final String PERSON_NAME = "name";
        public static final String PERSON_AGE = "age";
        public static final String PERSON_SEX = "sex";
        public static final String TABLE_NAME = "person";
        public static final String DATABASE_NAME = "db_person";

        public static final String CREATE_TABLE = "create table "+TABLE_NAME +"("
                + ID + " integer primary key autoincrement, "
                +PERSON_NAME + " text, "
                +PERSON_AGE + " integer, "
                +PERSON_SEX + " text)";

    }
}

美高梅网上注册平台 6SharedPreferences读取数据

新建MyDatabaseHelper继承自SQLiteOpenHelper:

之前在讲ListView的时候讲过了数据库存储。Android 对数据库的支持很好,自身就支持SQLite 这种轻量级的数据库,它的运算速度快,占用资源少,通常几百KB的内存就够了,并且支持标准的SQL语法,遵循数据库的ACID事务(是Atomic、Consistency、Isolation和Durability的英文缩写)。相比较一般的数据库上手简单。 在存储一些简单的数据和键值对的时候,可能会用上SharedPreferences存储。但是需要存储大量的复杂的关系型数据的时候,SharedPreferences显然不能满足要求,这时候就需要SQLite数据库的存储。数据库存储的主要操作:创建数据库,升级数据库,增,删,查,改操作。

public class MyDatabaseHelper extends SQLiteOpenHelper{

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

    @Override
    public void onCreate(SQLiteDatabase db) {

        db.execSQL(TableManager.PERSON_TABLE.CREATE_TABLE);
    }

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

    }
}

本文由美高梅网上注册平台发布于美高梅网上注册平台,转载请注明出处:  保存在内存中的数据是瞬时数据,文件存储

上一篇:没有了 下一篇:课程成绩高的所有学生的学号,课程成绩高的所
猜你喜欢
热门排行
精彩图文