分类
- 共享参数存储
- File存储(内部,外部)
- SQLite数据库
- Content Provider
- 网络存储
共享参数存储 Shared Preferences
特点
- 存放轻量级的数据
- 本质上xml的格式存数据,通过键值对的方式对数据进行读写
- 应用程序被卸载后,文件也会被删除
存储数据的类型
boolean# # int String long float
路径
data/data/包名/shared_preds/名字.xml
存储数据
SharedPreferences sPreferences=getSharedPreferences(name,mode)//得到SharedPreferences对象
Editor editor = sPrefences.edit();//得到共享参数的编辑对象
editor.putString(key,value);//向共享参数中存入数据
editor.commit();//别忘记提交
读取数据
SharedPreferences sPreference=getSharedPreferences(name,mode);//得到SharedPreferences对象 String msg=sPreference.getString(key,defValue);//根据key读取数据defValue为默认值
SharedPreferences源码
public interface SharedPreferences { void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key); } public interface Editor { //存数据,需要定义Editer Editor putString(String key, @Nullable String value); Editor putStringSet(String key, @Nullable Set values); Editor putInt(String key, int value); Editor putLong(String key, long value); Editor putFloat(String key, float value); Editor putBoolean(String key, boolean value); Editor remove(String key); Editor clear(); boolean commit(); void apply(); } //取数据 Map
File存储
内部存储 Internal Storage
特点
- 文件只能被当前应用程序访问,其他应用程序不能访问
- 文件卸载后,其中的数据也会随之清除
路径
data/data/包名/files/xxx.xxx(名字.类型)
存入数据
FileOutputStream fos=openFileOutput(fileName,mode);//打开文件输出流 fos.write(byte[]);//写入数据 fos.close();//关闭流
取出数据
FileInputStream fis=openFileInput(fileName);//打开文件输入流 byte[] buffer=new byte[fis.avaiable()];//读取数据 fis.read(buffer); //这儿可以根据要读取的数据类型,定义相应的接收 fis.close()//关闭流
外部存储 External Storage
特点
- sdcard分为两个部分,一个为公共目录,一个是私有目录
- 公共目录下的文件可以被其他目录访问,私有目录的只能被本应用程序访问
- 卸载应用程序后,sd公共目录中的文件不会比清除,私有目录中的文件会被清除
路径
- 公有:storage/sdcard
- 私有:storage/sdcard/Android/data/包名/files/
权限问题
- WRITE_EXTERNAL_STORAGE 写sd卡权限
- READ_EXTERNAL_STORAGE 读sd卡权限
- 注意:有时用studio自带的模拟器,加了权限,在运行时,却不能存入,提示FileNotFound及权限问题,这是模拟器的问题,用手机或者换个模拟器就行了
sd卡的状态
sd卡的状态可以用Environment.getExternalStorageState()判断
MEDIA_MOUNTED为挂载状态,表示可以使用
获得目录路径
- Environment.getExternalStoragePublicDirectory();//公共目录
- Environment.getExternalStorageDirectory();//私有目录
Environment中对应源码
//其中一些对象Environment中内部类UserEnvironment定义的 public static String getExternalStorageState() { final File externalDir = sCurrentUser.getExternalDirs()[0]; return getExternalStorageState(externalDir); } public static File getExternalStorageDirectory() { throwIfUserRequired(); return sCurrentUser.getExternalDirs()[0]; } public static File getExternalStoragePublicDirectory(String type) { throwIfUserRequired(); return sCurrentUser.buildExternalStoragePublicDirs(type)[0]; }
数据库存储
一些数据库
Oracle SQLServier Mysql SQLite
SQLite
Android系统中集成的轻量级的数据库
特点
- 轻量级:一个动态的数据库,以单个文件的方式进行存取
- 零配置:无需安装
- 跨平台:可以支持多个操作系统
- 嵌入式:嵌入手机
存放的数据类型
- NULL 空值
- INTENGER 整型
- VARCHAR 可变长度的字符数据
- TEXT 文本字符串
- BOOLEAN 布尔
sql语句
//创建 create table if not exists 表名(字段名 字段类型 primary key autoincrement,字段名 字段类型,...) //插入 insert into 表名(字段)Values(值) //修改 update 表名 set 字段名=值 where 条件 //查询 select(显示的字段) from 表名 where 条件 //删除 delete from 表名 where 条件
数据库核心类
SQLiteDatabase 管理和操作数据库
特点
- 提供了一个管理数据库的类
- 提供了增删改查数据库的方法
- 数据库的名称在当前应用程序中是唯一的, 而不是在所有应用程序值唯一
SQLiteDatabase db=openOrCreateDatabase(name,mode,factory); //name,数据库名称; //mode,数据库访问权限; //factory,游标工厂. //执行数据库操作的方式://1、直接: String sql="insert into person(name,age) values('张三',21)"; //sql为数据库语言 db.execSQL(sql);//2、使用SQLiteDatabase里封装好的一些方法 //查 /** * distinct 去除重复 * table 表名 * columns 字段 new String[]{"_id","name","age"} 如果查询所有数据, 则null * selection 条件 where之后的内容 * selectionArgs 占位符的取值 * groupBy 分组 * having 放在where之后再次筛选 * orderBy 排序 * limit 区间 */ db.query(distinct, table, columns, selection, selectionArgs, groupBy, having, orderBy,limit); //删 /*** * table 表名 * whereClause 删除的条件 where之后的内容 * whereArgs 占位符的取值 */ db.delete(table, whereClause, whereArgs); //改 /** * table 表名 * values ContentValues * whereClause 条件 占位符 where 之后的内容 * whereArgs 占位符对应的值 */ db.update(table, values, whereClause, whereArgs); //增 /** * table 表名 * nullColumnHack null insert into person (nullColumnHack) values(null) * values ContentValues(key,value) */ db.insert(table, nullColumnHack, values); //其中ContentValues(key,value)创建使用 //key 表中的字段名称, value 对应的数据内容 ContentValues values = new ContentValues(); values.put("name", "行文不及码如风"); values.put("age", 23);
Context类中部分代码:
/** * Open a new private SQLiteDatabase associated with this Context's * application package. Create the database file if it doesn't exist. */ public abstract SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory);/** * Open a new private SQLiteDatabase associated with this Context's * application package. Creates the database file if it doesn't exist. */ public abstract SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory, DatabaseErrorHandler errorHandler);/** * Delete an existing private SQLiteDatabase associated with this Context's * application package. */ public abstract boolean deleteDatabase(String name);/** * Returns the absolute path on the filesystem where a database created with */ public abstract File getDatabasePath(String name);/** * Returns an array of strings naming the private databases associated with * this Context's application package. */ public abstract String[] databaseList();
SQLiteDatabase中部分源码:
public void execSQL(String sql) throws SQLException { executeSql(sql, null); }public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) { return query(false, table, columns, selection, selectionArgs, groupBy, having, orderBy, null /* limit */); }public long insert(String table, String nullColumnHack, ContentValues values) { try { return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE); } catch (SQLException e) { Log.e(TAG, "Error inserting " + values, e); return -1; } }public int delete(String table, String whereClause, String[] whereArgs) { SQLiteStatement statement = new SQLiteStatement(this, "DELETE FROM " + table + (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs); try { return statement.executeUpdateDelete(); } catch (SQLiteDatabaseCorruptException e) { onCorruption(); throw e; } finally { statement.close(); } }public int update(String table, ContentValues values, String whereClause, String[] whereArgs) { return updateWithOnConflict(table, values, whereClause, whereArgs, CONFLICT_NONE); }
SQLiteOpenHelper 用于数据库的创建和版本更新
作用
- 初始化数据库
- 升级数据库 (更新)
- 打开数据库连接 (存在则打开,不存在则创建并打开连接)
使用
//定义一个类继承SQLiteDatabase public class MySqliteHepler extends SQLiteOpenHelper{ //提供一个构造方法 public MySqliteHepler(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); // TODO Auto-generated constructor stub } @Override public void onCreate(SQLiteDatabase db) { // TODO Auto-generated method stub //第一次创建数据库时执行, 只会执行一次 } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // TODO Auto-generated method stub //当数据库的版本号发生变化后, 执行此方法, 会执行多次 } }MySqliteHepler helper=new MySqliteHepler(context); SQLiteDatabase db = helper.getWritableDatabase(); SQLiteDatabase db = helper.getReadableDatabase(); ...
Cursor
默认游标的位置位于所有数据之上
boolean cursor.move(offset) 游标向上或者向下移动指定的条数,并且判断是否存在
boolean cursor.moveToNext() 游标移动到下一条数据, 并且判断下一条数据是否存在
boolean cursor.moveToPrevious() 游标移动到上一条数据, 并且判断上一条数据是否存在
boolean cursor.moveToFirst() 游标移动到第一条数据, 并且判断第一条数据是否存在
boolean cursor.moveToLast() 游标移动到最一条数据, 并且判断最一条数据是否存在
boolean cursor.moveToPosition() 游标移动到指定数据, 并且判断该数据是否存在
int cursor.getCount() 得到游标中所以数据的数量
取值:
获取内容: cursor.getString(列的编号) // 列的编号从0开始
根据列的名称得到列的编号: cursor.getColumnIndex(字段名称)
SimpleCursorAdapter
特点
- 数据源中必须要包括一个”_id” 的字段
- 刷新适配器, 没有效果
/** * context 上下文对象 * layout 每个Item显示的布局页面 * c 游标(数据源) * from String[] cursor中所有字段名称的数组 * to int[] 布局页面中Id的数组 * flags 标记, 自动更新(观察者) */ SimpleCursorAdapter adapter = new SimpleCursorAdapter( context, layout, c, from, to, flags); //例如: SimpleCursorAdapter adapter = new SimpleCursorAdapter( this, R.layout.item, //子布局 cursor, new String[]{"name","age"},//两个属性名 new int[]{R.id.name,R.id.age},//两个属性对应的子布局中控件id SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
Content Provider
是什么
特点
- 所有应用程序之间数据存储和检索的桥梁
- 应用程序之间数据共享的唯一途径
注意
- 如果想访问内容提供者提供的数据,那么需要通过ContentResolver对象获取数据内容
- 想要共享自己的数据,那么需要自定义一个内容提供者,把自己的数据共享出去
做什么
- 实现多个应用程序之间的共享
URI
- content://应用程序包名.provider/表名 —自定义
分析
- ContentResolver 内容更解析器:负责解析ContentProvider暴露出来的数据
- ContentProvider 内容提供者:负责暴露数据
实例
访问手机中提供的数据
访问短信记录
private ListView listView; private Cursor cursor; private SimpleCursorAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView=(ListView) findViewById(R.id.list_view); //得到数据源 //得到内容解析器对象 ContentResolver contentResolver=getContentResolver(); //解析数据 /** * uri 访问ContentProvider提供的路径 * projection 查询数据库中的字段 * _id, address 地址, data 日期, body 内容, type 短信类型 * type (1接收,2发送,3草稿箱,4未读的短信,5发送失败的短信 ) * selection 查询的条件 * selectionArgs 占位符的取值 * sortOrder 排序 */ Uri uri=Uri.parse("content://sms"); String [] projection=new String[]{"_id","address","date","body","type"}; cursor=contentResolver.query(uri, projection, null, null, null); adapter=new SimpleCursorAdapter( getApplicationContext(), R.layout.item, cursor, new String[]{"address","body"}, new int[]{R.id.content_address,R.id.content_body}, SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER); listView.setAdapter(adapter); }
自定义ContentProvider
- 定义一个类, 继承ContentProvider, 重写父类的6个方法
onCreate()初始化工作 query(Uri uri,....) 查询数据 insert(Uri uri,....) 插入数据 update(Uri uri,...) 修改数据 delete(Uri uri,..) 删除数据 getType() 只实现, 不处理
- 声明ContentProvider的唯一标识 (内容只能为小写的字母,建议使用: 包名+数据库的名称)
- 声明访问数据库的Code码 (在ContentProvider 暴露数据时使用)
- 声明Uri的匹配器,并且实例化, 注册Uri
private static UriMatcher uriMatcher; static{ uriMatcher = new UriMatcher(UriMatcher.NO_MATCHER); uriMatcher.addUri(唯一标识, 路径
网络存储
Android提供了通过网络来实现数据的存储和获取的方法。
我们可以调用WebService返回的数据或是解析HTTP协议实现网络数据交互。
具体需要熟悉Java.NET.* ,Android.Net.* 这两个包的内容,详细的类与方法的说明,请参考SDK