分享

[Android]Android数据的四种存储方式 - Ron Ngai - 博客园

 昵称29238710 2015-11-14
存储方式

Android提供以下四种存储方式:

  • SharePreference
  • SQLite
  • File
  • ContentProvider
Android系统中数据基本都是私有的,一般存放在“data/data/程序包名”目录下。如果要实现数据共享,正确的方式是使用ContentProvider。

SharedPreference
SharedPreference是一种轻型的数据存储方式,实际上是基于XML文件存储的“key-value”键值对数据。通常用来存储程序的一些配置信息。其存储在“data/data/程序包名/shared_prefs目录下。
SharedPreference本身只能获取数据,不支持存储和修改。存储和修改要通过Editor对象来实现。
 
修改和存储数据
  • 根据Context的getSharedPrerences(key, [模式])方法获取SharedPreference对象;
  • 利用SharedPreference的editor()方法获取Editor对象;
  • 通过Editor的putXXX()方法,将键值对存储数据;
  • 通过Editor的commit()方法将数据提交到SharedPreference内。
综合例子
    //设置单例里面的数值,然后再将数值写入到SharedPreference里
复制代码
    private String setCityName(String _cityName){        City.getCity().setCityName(_cityName);                Context ctx =MainActivity.this;        SharedPreferences sp =ctx.getSharedPreferences('CITY', MODE_PRIVATE);        Editor editor=sp.edit();        editor.putString('CityName', City.getCity().getCityName());        editor.commit();                return City.getCity().getCityName();    }
复制代码

 

获取数据
  • 同样根据Context对象获取SharedPreference对象;
  • 直接使用SharedPreference的getXXX(key)方法获取数据。
综合例子:
    //从单例里面找,如果不存在则在SharedPreferences里面读取
复制代码
    private String getCityName(){        String cityName = City.getCity().getCityName();        if(cityName==null ||cityName==''){            Context ctx =MainActivity.this;            SharedPreferences sp =ctx.getSharedPreferences('CITY', MODE_PRIVATE);            City.getCity().setCityName(sp.getString('CityName', '广州'));        }        return City.getCity().getCityName();    }
复制代码
注意
  • getSharedPrerences(key, [模式])方法中,第一个参数其实对应到XML的文件名,相同key的数据会保存到同一个文件下。
  • 使用SharedPreference的getXXX(key)方法获取数据的时候,如果key不存在的活,不会出现报错,会返回none。建议使用getXXX()的时候指定默认值。

SQLite
SQLite是一个轻量级关系型数据库,既然是关系型数据库,那操作起来其实跟mysql、sql server差不多的。
需要注意的一点是,SQLite只有NULL、INTEGER、REAL(浮点数)、TEXT(字符串)和BLOB(大数据)五种类型,不存在BOOLEAN和DATE类型。
 
创建数据库
        通过openOrCreateDatabase(String path, SQLiteDatabase.CursorFactory factory)方法创建,如果库已创建,则打开数据库。
SQLiteDatabase db =this.openOrCreateDatabase('test_db.db', Context.MODE_PRIVATE, null);
创建表
        SQLiteDatabase没有提供创建表的方法,所以要靠execSQL()方法来实现。看名字也知道execSQL()用于直接执行sql的。
复制代码
String sql='create table t_user (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL,password TEXT NOT NULL)';db.execSQL(sql);
复制代码
        使用SQLiteDatabase的insert(String table, String nullColumnHack, ContentValues values)方法插入数据。ContentValues 类,类似于java中的Map,以键值对的方式保存数据。
复制代码
ContentValues values=new ContentValues();values.put('name', 'liangjh');values.put('password', '123456');db.insert('t_user', 'id', values);
复制代码
 
        删除数据就比较直接了。使用SQLiteDatabase的delete(String table, String whereClause, String[] whereArgs)实现。如果不想把参数写在whereArgs里面,可以直接把条件写在whereClause里面。
复制代码
// 方式1 直接将条件写入到条件里面(个人觉得容易被注入,但其实数据都在客户端,没啥安全性可言)db.delete('t_user', 'id=1', null);// 方式2 条件分开写,感觉比较安全db.delete('t_user', 'name=? and password =?', new String[]{'weiyg','112233'});
复制代码

 

        查询有2个方法,query()和rawQuery()两个方法,区别在于query()是将sql里面的各参数提取出query()对应的参数中。可参考下面例子。
复制代码
// 使用rawQuery// Cursor c = db.rawQuery('select * from t_user', null);// db.rawQuery('select * from t_user where id=1', null);// db.rawQuery('select * from t_user where id=?', new String[]{'1'}); // 使用query()Cursor c = db.query('t_user', new String[]{'id','name'}, 'name=?', new String[]{'weiyg'}, null, null, null);c.moveToFirst();while(!c.isAfterLast()){    String msg='';    for(int i=0,j=c.getColumnCount();i<j;i++){        msg+='--'+c.getString(i);    }    Log.v('SQLite', 'data:'+msg);    c.moveToNext();}
复制代码
 
        使用SQLiteDatabase的update(String table, ContentValues values, String whereClause, String[] whereArgs)可以修改数据。whereClause和whereArgs用于设置其条件。ContentValues对象为数据。
复制代码
ContentValues values=new ContentValues();values.put('password', '111111');// 方式1 条件写在字符串内db.update('t_user', values, 'id=1', null);// 方式2 条件和字符串分开db.update('t_user', values, 'name=? or password=?',new String[]{'weiyg','123456'});
复制代码
 
其它

无论何时,打开的数据库,记得关闭。

复制代码
db.close()
复制代码

另外使用beginTransaction()和endTransaction()可以设置事务。

 


File
        文件储存方式,很久以前讲过,这里不说明。
 

 
ContentProvider
ContentProvider相对于其它的方式比较复杂,当然其功能相对于其它的方式也是革命性的改变。它能够实现跨应用之间的数据操作。利用ContentResolver对象的delete、update、insert、query等方法去操ContentProvider的对象,让ContentProvider对象的方法去对数据操作。实现方式为:
  • 在A程序中定义一个ContentProvider,重载其增删查改等方法;
  • 在A程序中的AndroidManifest.xml中注册ContentProvider;
  • 在B程序中通过ContentResolver和Uri来获取ContentProvider的数据,同样利用Resolver的增删查改方法来获得和处理数据。
在A程序定义一个Provider
新建一个类,继承ContentProvider,并重载其delete()、insert()、query()、update()、getType()、onCreate()方法。譬如下面的例子,重载其onCreate和query方法。
复制代码
 1 public class MyProvider extends ContentProvider { 2  3     @Override 4     public int delete(Uri uri, String selection, String[] selectionArgs) { 5         // TODO Auto-generated method stub 6         return 0; 7     } 8  9     @Override10     public String getType(Uri uri) {11         // TODO Auto-generated method stub12         return null;13     }14 15     @Override16     public Uri insert(Uri uri, ContentValues values) {17         // TODO Auto-generated method stub18         return null;19     }20 21     @Override22     public boolean onCreate() {23         // 新建个数据库并插入一条数据24         SQLiteDatabase db=this.getContext().openOrCreateDatabase('test_db2.db', Context.MODE_PRIVATE, null);25         db.execSQL('CREATE TABLE t_user (id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT NOT NULL)');26         ContentValues values=new ContentValues();27         values.put('name', 'liangjh2');28         db.insert('t_user', 'id', values);29         db.close();30         return false;31     }32 33     @Override34     public Cursor query(Uri uri, String[] projection, String selection,35             String[] selectionArgs, String sortOrder) {36         // 获取数据37         SQLiteDatabase db=this.getContext().openOrCreateDatabase('test_db2.db', Context.MODE_PRIVATE, null);38         Cursor c = db.query('t_user', null, null, null, null, null, null);39         db.close();40         return c;41     }42 43     @Override44     public int update(Uri uri, ContentValues values, String selection,45             String[] selectionArgs) {46         // TODO Auto-generated method stub47         return 0;48     }49 50 }
复制代码
 
 
注册ContentProvider
在AndroidManifest.xml中声明ContentProvider,authorities属性定义了ContentProvider的Uri标识。关于Uri标识属另一个范畴,自行查询。provider标识要放在<application></application>里面。如果遇到了'Permission Denial: opening provide...'的错误,可以试试在节点加“android:exported='true'”。
复制代码
<application ...>    ...    <provider android:name='.MyProvider' android:authorities='com.example.androidtestdemo' android:exported='true'/></application>
复制代码

 

在B程序获取数据
用Context获取到当前的ContentResolver,根据Uri地址和ContentResolver的query方法获取A程序的数据。Uri地址和A程序中AndroidManifest.xml定义的autorities要一致。当然,同类可以进行其它的操作。
复制代码
Context ctx=MainActivity.this;ContentResolver resolver =ctx.getContentResolver();Uri uri=Uri.parse('content://com.example.androidtestdemo');Cursor c = resolver.query(uri, null, null, null, null);c.moveToFirst();while(!c.isAfterLast()){    for(int i=0,j=c.getColumnCount();i<j;i++){        Log.v('Android2',''+c.getString(i));    }    c.moveToNext();}
复制代码

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多