您的位置:首页 > 移动开发 > Android开发

Android数据持久化存储方式

2016-12-02 19:30 363 查看
Android系统中主要提供了三种方式用于简单的实现数据持久化功能:

文件存储(手机自带的内存)SharedPreferences存储以及数据库存储
当然还可以用sd卡存储

1,文件存储

特点:手机自带的内存,只能供当前应用程序访问,其他应用程序访问不了,程序卸载这些数据也会随着消失

原理:
基本是先获取一个文件的输出流,然后把信息write进去,最后关闭流
a,通过上下文类context的openFileOutput()方法获得一个FileOutputStream输出流
b,要写入的内容通过write()写到FileOutputStream对象
c,关闭流
openFileOutput()可以将数据存储到指定的文件中,方法有两个参数,第一个参数是文件名,不需要带上完整的路径,因为这里都是默认存储到data/data/file下面的

第二个参数是文件的操作模式,两种:MODE_PRIVATE和MODE_APPEND.前者是覆盖,后者是追加
(MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE,前者是允许只读,后者是只写,但是都被抛弃,因为不安全)

[java] view
plain copy

private void save(String inputText ) {  

           FileOutputStream fos = null;  

           BufferedWriter writer = null;  

            try {  

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

               writer = new BufferedWriter( new OutputStreamWriter(fos));  

                writer.write( inputText);  

           } catch (IOException e) {  

                 // TODO Auto-generated catch block  

                 e.printStackTrace();  

           } finally {  

                 try {  

                      if( writer != null)  

                            writer.close();  

                }catch (IOException e) {  

                      // TODO Auto-generated catch block  

                      e.printStackTrace();  

                }  



[align=left]主要的就是上面的三句话[/align]
[align=left]openFileOutput打开一个输出流,然后构建一个字节缓冲流对象然后写数据,[/align]
[align=left]
[/align]

[align=left]此外还有几个方法需要特别注意一下 ,这几个方法对于文件关系提供了更好的支持,配合上面介绍的方式, 就可以对文件的数据进行常规的CRUD操作 (增删改查),方法如下:[/align]
[align=left]File getFIlesDir ():获取文件系统的绝对路径。[/align]
[align=left]boolean deleteFile(String name):删除一个指定文件名为name的文件。[/align]
String[] fileList() :当前应用内部存储路径下的所有文件名。
[align=left]
[/align]

[java] view
plain copy

 //帮助我们返回一个目录  

  //context.getCacheDir ()的话就是保存到cache缓存文件夹下面       

File file=new File(context.getFilesDir(), "userinfo.txt");             

       FileOutputStream fos= new FileOutputStream( file);            

            //zhangsan 123  

            fos.write(( username+ "##"+ password).getBytes());  

            fos.close();  

2、sharedpreference
存储(一般用于保存用户设置偏好);


特点如下:

@1

以键值对的形式保存到data/data/应用程序包名/shared_prefs目录的XXX.xml文件中


@2目前支持的数据类型有String
int float boolean long


@3不支持自定义的Object

@4通常用来存储App上的用户配置信息.如:是否震动,是否打开背景音乐
小游戏积分 用户账号密码信息

[align=left]要使用该方法来存储数据就要先获得一个SharedPreferences对象,有三种获取方法[/align]
[align=left]a,Context上下文类中的getSharedPreferences[/align]
[align=left]两个参数,第一个是指定文件的名称,不在就创建。目录也是在data/data/包名/shared_prefs目录下[/align]
[align=left]第二个参数是操作模式。MODE_PRIVATE是默认的,只允许当前的应用程序对其进行操作,MODE_MULTI_PROCESS是一般用于有多个进程中对同一个SharedPreferences文件进行读写的情况,同样有MODE_WORLD_WRITEABLE MODE_WORLD_READABLE两个被废弃的模式[/align]
[align=left]b,Activity类中的getPreferences[/align]
[align=left]只有一个参数,也是操作模式,文件的名称是默认的当前活动的类名[/align]
[align=left]c,PreferenceManager管理类中的getDefaultSharedPreferences()[/align]
[align=left]管理类中的一个静态方法,接收一个context参数,自动把当前的包名作为文件命名的前缀[/align]
[align=left]
[/align]
[align=left]得到一个对象之后,有三步来进行数据的存储[/align]
[align=left]1,调用对象的edit方法获得一个SharedPreferences.Editor对象[/align]
[align=left]2,向.Editor对象添加数据,putBoolean()或者是putString(),,等等putXXX()方法[/align]
[align=left]3,调用commit方法将添加的数据提交,完成数据的存储操作[/align]
[align=left]
[/align]
[align=left]例子:[/align]

[java] view
plain copy

@Override  

public void onClick(View v) {  

      // TODO Auto-generated method stub  

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

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

             editor.putInt( "id", 9527);  

             editor.putBoolean( "婚否", false );  

             editor.commit();          

           }  

     });  

最后的结果是以xml的方式存在内存中的

[align=left]从SharedPreferences中读取数据 SharedPreferences提供了许多的get方法来进行获取数据,都和相应的put方法对应[/align]
[align=left]get方法也是有两个参数,第一个“键”,第二个是键找不到值时候的默认值,自己设定把[/align]

[align=left]还是继续取出上面存储的xml数据文件的数据 [/align]

[java] view
plain copy

restore_button .setOnClickListener(new OnClickListener() {             

            @Override  

            public void onClick(View v) {  

                 // TODO Auto-generated method stub  

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

             

           String name= pref.getString( "name", "HuaAn");  

            int id= pref.getInt( "id", 9527);  

            boolean married= pref.getBoolean( "婚否", false ); 

           }  

     });  

     }  

3 ,SQLite数据库存储



[align=left]为方便管理数据库有一个专门的抽象类SQLiteOpenHelper,它有两个抽象的方法onCreate()和onUpdate()[/align]
[align=left]此外还有两个实例方法,getReadableDatabase()和getWritableDatabase(),都可以创建或者是打开一个现有的数据库(存在就打开,不在就创建),返回一个可对数据库进行操作的对象[/align]
[align=left]当数据库不可写入的时候,前者返回的是一个只能读的方式打开数据库,后者则会出现异常[/align]
[align=left]
[/align]
[align=left]数据库文件同样还是会放在data/data/包名/databases下面[/align]

实现步骤如下:

[align=left]1,构建SQLiteOpenHelper的实例,也就是完成其构造函数(参数一是context,第二个是要创建的数据库的名字,第三个是cursor,一般是null,第四个是数据库的版本号)[/align]
[align=left]2,再调用getReadableDatabase()或者getWritableDatabase()方法创建数据库[/align]
[align=left]同时重写onCreate()方法,该方法也会得到执行[/align]
例子:

[java] view
plain copy

public class MyDatabaseHelper extends SQLiteOpenHelper {  

/* 

补充一下建表的一些类型 

integer ---整型 

real-----浮点类型 

text---文本类型 

blob---二进制类型 

 

*/  

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,  

                CursorFactory factory, int version) {  

            super( context, name, factory, version);  

            // TODO Auto-generated constructor stub  

            mContext= context;  

     }  

  

     @Override  

     public void onCreate(SQLiteDatabase db) {  

            // TODO Auto-generated method stub  

//执行建表语句  

    db.execSQL(CREATE_BOOK);  

    Toast.makeText(mContext , "数据库创建成功" , Toast.LENGTH_SHORT).show();  

     }  

  

     @Override  

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

            // TODO Auto-generated method stub  

     }  

}  

dbHelper= new MyDatabaseHelper( this, "BookStore.db", null, 1);  

     Button createDatabase=(Button) findViewById(R.id.create_database );  

     createDatabase.setOnClickListener( new OnClickListener() {  

             

            @Override  

            public void onClick(View v) {  

                 // TODO Auto-generated method stub  

                 dbHelper. getWritableDatabase();  

           }  

     });  




public long insert (String table, String nullColumnHack, ContentValues values)

Added in API level 1

Convenience method for inserting a row into the database.

Parameters
tablethe table to insert the row into
nullColumnHackoptional; may be 
null
. SQL doesn't allow inserting a completely empty row without naming at least one column name. If your provided 
values
 is
empty, no column names are known and an empty row can't be inserted. If not set to null, the
nullColumnHack
 parameter provides the name of nullable column name to explicitly insert a
NULL into in the case where your 
values
 is empty.
valuesthis map contains the initial column values for the row. The keys should be the column names and the values the column values
Returns
the row ID of the newly inserted row, or -1 if an error occurred

[java] view
plain copy

Button addData =(Button) findViewById(R.id. add_data);  

      addData.setOnClickListener( new OnClickListener() {           

            @Override  

            public void onClick(View v) {  

                 // TODO Auto-generated method stub  

                SQLiteDatabase dbOperate= dbHelper.getWritableDatabase();  

                ContentValues values= new ContentValues();  

            //下面没有给表中的id赋值,因为在建表的时候,id是默认自动增长的  

                 //添加第一条记录到Book  

                 values.put( "name", "安卓入门之路" );  

                 values.put( "author", "hl174");  

                 values.put( "pages", 800);  

                 values.put( "price", 50);                 

                 dbOperate.insert( "book", null, values);  

                  

                 values.clear();  

                  

                 //插入第二条记录到book  

                 values.put( "name", "安卓精通" );  

                 values.put( "author", "hl174");  

                 values.put( "pages", 700);  

                 values.put( "price", 45);       

              dbOperate.insert( "book", null, values);  

           }  

     });  

[align=left]更新数据:[/align]
[align=left]update():四个参数[/align]


public int update (String table, ContentValues values, String whereClause, String[]whereArgs)

Added in API level 1

Convenience method for updating rows in the database.

Parameters
tablethe table to update in
valuesa map from column names to new column values. null is a valid value that will be translated to NULL.
whereClausethe optional WHERE clause to apply when updating. Passing null will update all rows.
whereArgsYou may include ?s in the where clause, which will be replaced by the values from whereArgs. The values will be bound as Strings.
Retu rns
the number of rows affected

[align=left]第一个参数:表名  第二个参数:ContentValues对象,[/align]
[align=left]最后两个参数是用来约束更新某一行或几行中的数据,不指定的话就是更新所有行[/align]

[java] view
plain copy

//更新数据  

     Button updateData=(Button) findViewById(R.id. update_data);  

      updateData.setOnClickListener( new OnClickListener() {  

            @Override  

            public void onClick(View v) {  

                 // TODO Auto-generated method stub  

                SQLiteDatabase db= dbHelper.getWritableDatabase();  

                ContentValues values= new ContentValues();  

                 values.put( "price", 10000);  

                  

        db.update( "book", values, "name=?", new String[]{"安卓入门之路" });  

           }  

     });  

[align=left]上面第三个参数对应的是类似sql中的where语句,?是一个占位符,第四个参数的内容可以替换掉该占位符[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]删除数据[/align]
[align=left]很明显,删除数据就是delete()方法了[/align]


public int delete (String table, String whereClause, String[] whereArgs)

Added in API level 1

Convenience method for deleting rows in the database.

Parameters
tablethe table to delete from
whereClausethe optional WHERE clause to apply when deleting. Passing null will delete all rows.
whereArgsYou may include ?s in the where clause, which will be replaced by the values from whereArgs. The values will be bound as Strings.
Returns
the number of rows affected if a whereClause is passed in, 0 otherwise. To remove all rows and get a count pass "1" as the whereClause.

[align=left]三个参数:第一个是表名[/align]
[align=left]第二个第三个同样是进行约束的条件行[/align]

[java] view
plain copy

//删除数据  

     Button deleteData=(Button) findViewById(R.id. delete_data);  

      deleteData.setOnClickListener( new OnClickListener() {        

            @Override  

            public void onClick(View v) {  

                 // TODO Auto-generated method stub  

                SQLiteDatabase db= dbHelper.getWritableDatabase();  

                 //删除页数大于500的记录  

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

           }  

     });  

查询语句
[align=left]CRUD中其实用的最多的还是查询语句[/align]
[align=left]同样SQLiteDatabase也提供了query()方法,但是这个方法有好多个参数的类型,看最少的参数为7个[/align]


public Cursor query (String table, String[] columns, String selection, String[]selectionArgs, String groupBy, String having, String orderBy)

Added in API level 1

Query the given table, returning a 
Cursor
 over
the result set.

Parameters
tableThe table name to compile the query against.
columnsA list of which columns to return. Passing null will return all columns, which is discouraged to prevent reading data from storage that isn't going to be used.
selectionA filter declaring which rows to return, formatted as an SQL WHERE clause (excluding the WHERE itself). Passing null will return all rows for the given table.
selectionArgsYou may include ?s in selection, which will be replaced by the values from selectionArgs, in order that they appear in the selection. The values will be bound as Strings.
groupByA filter declaring how to group rows, formatted as an SQL GROUP BY clause (excluding the GROUP BY itself). Passing null will cause the rows to not be grouped.
havingA filter declare which row groups to include in the cursor, if row grouping is being used, formatted as an SQL HAVING clause (excluding the HAVING itself). Passing null will cause all row groups to be included, and is required when row grouping is not being
used.
orderByHow to order the rows, formatted as an SQL ORDER BY clause (excluding the ORDER BY itself). Passing null will use the default sort order, which may be unordered.
Returns
Cursor
 object,
which is positioned before the first entry. Note that 
Cursor
s
are not synchronized, see the documentation for more details.

See Also
Cursor


[align=left]1:表名[/align]
[align=left]2:要查询的是哪几列,不指定的话就是默认查询所有列[/align]
[align=left]3、4:约束某一行或者是某几行的数据,不指定则默认是查询所有的数据[/align]
[align=left]5,groupby指定的列,不指定这项参数就相当于跳过[/align]
[align=left]6,having是对group之后的数据进行过滤[/align]
[align=left]7可以指定查询结果的排序方式[/align]
[align=left]
[/align]
[align=left]当然调用query之后会返回一个Cursor对象,查询到的数据都将从这个对象中取出[/align]

[java] view
plain copy

public void onClick(View v ) {  

          // TODO Auto-generated method stub  

       SQLiteDatabase db= dbHelper.getWritableDatabase();  

        //查询book表中的所有数据  

 Cursor cursor=  db.query( "book", null, null, null, null, null, null);  

   if( cursor.moveToFirst()){  

          do{  

             //遍历cursor对象,取出数据并打印  

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

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

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

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

                             

         Log. d("MainActivity" , "书名是:" +name );  

         Log. d("MainActivity" , "书的作者是:" +author );  

         Log. d("MainActivity" ,"书的页数是:" +pages );  

         Log. d("MainActivity" , "书的价钱是:" +price );  

          } while( cursor.moveToNext());  

         }  

     cursor.close();  

    }  

  });  

[align=left]首先是通过db.query得到cursor对象,在cursor类中我们发现了下面的一些方法,getString,getDouble,getInt等但是都需要传一个参数进去,也就是所在列的下标,从0开始计数[/align]
[align=left]要得到相应列所在的下标同样有方法getColumnIndex(String columnName),这样的话先得到列所在的下标,然后通过该下标得到相应的记录值[/align]




public abstract int getColumnIndex (String columnName)

Added in API level 1

Returns the zero-based index for the given column name, or -1 if the column doesn't exist. If you expect the column to exist use 
getColumnIndexOrThrow(String)
 instead,
which will make the error more clear.

Parameters
columnNamethe name of the target column.
Returns
the zero-based column index for the given column name, or -1 if the column name does not exist.

See Also
getColumnIndexOrThrow(String)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: