1.sharedpreference
简介:保存检索基本数据类型(boolean float int long string)的键值对(基于XML文件存储的“key-value”)
存储位置:data/data/程序包名/shared_prefs目录下
数据读写:
//写入
SharedPreferences mySharedPreferences= getSharedPreferences("Test",Activity.MODE_PRIVATE);//实例化SharedPreferences对象
SharedPreferences.Editor editor = mySharedPreferences.edit();//实例化SharedPreferences.Editor对象
editor.putString("t", "要保存的数据");//用putString的方法保存数据
editor.commit();//提交
//取值
SharedPreferences settings = getSharedPreferences("Test",Activity.MODE_PRIVATE);
String get = settings.getString("t","");
//删除
SharedPreferences mSharedPreferences= getSharedPreferences("Test",Activity.MODE_PRIVATE);
SharedPreferences.Editor meditor = mSharedPreferences.edit();
meditor.remove("key");//下一次commit的时候会移除key对应的键值对
meditor.clear();//移除所有键值对
editor.commit();
应用范围:很轻量级的应用,使用起来也很方便,简洁。但存储数据类型比较单一(只有基本数据类型),无法进行条件查询,只能在不复杂的存储需求下使用,比如保存配置信息等
2.文件存储
2.1 内部存储
简介:文件被保存在内部存储中时,默认情况下,文件是应用程序私有的,其他应用不能访问。当用户卸载应用程序时这些文件也跟着被删除。
存储位置:data/data/程序包名/files/文件名
数据写入:
① 调用Context的openFileOutput()函数,填入文件名和操作模式,它会返回一个FileOutputStream对象。
② 通过FileOutputStream对象的write()函数写入数据。
③ FileOutputStream对象的close ()函数关闭流。
代码:
String FILENAME = "save.txt";
String string = "data";
/**
name参数: 用于指定文件名称,不能包含路径分隔符“/” ,如果文件不存在,Android 会自动创建它。
mode参数:用于指定操作模式,分为四种:
Context.MODE_PRIVATE = 为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容。
Context.MODE_APPEND = 32768 该模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。
Context.MODE_WORLD_READABLE = 1 表示当前文件可以被其他应用读取。
MODE_WORLD_WRITEABLE 表示当前文件可以被其他应用写入。
*/
try {
FileOutputStream fileOutputStream = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fileOutputStream.write(string.getBytes());
fileOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
数据读取:
① 调用openFileInput( ),参数中填入文件名,会返回一个FileInputStream对象。
② 使用流对象的 read()方法读取字节
③ 调用流的close()方法关闭流
代码:
//读取
String FILENAME1 = "save.txt";
try {
FileInputStream inputStream = openFileInput(FILENAME1);
int len = 0;
byte[] buf = new byte[1024];
StringBuilder sb = new StringBuilder();
while ((len = inputStream.read(buf)) != -1) {
sb.append(new String(buf, 0, len));
}
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
/** * 附:常用的一些方法 getFilesDir(): 获取内存储文件的绝对路径 getDir(): 在内存储空间中创建或打开一个已经存在的目录 deleteFile(): 删除保存在内部存储的文件 fileList(): 返回当前由应用程序保存的文件的数组(内存储目录下的全部文件) */
2.2 外部存储
简介:因为内部存储容量限制,有时候需要存储数据比较大的时候需要用到外部存储 存储位置:data/data/程序包名/files/文件名
添加权限:
<!-- SDCard创建、删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- SDCard写入权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
检测外部存储是否可用
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// 可读可写
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// 可读
} else {
// 有很多其他状态,但只需要知道不能读写(不深究原理过程细节的话)
}
访问外部存储器中的文件
API>8:
//该方法打开一个外存储目录,此方法需要一个类型,指定你想要的子目录,如类型参数DIRECTORY_MUSIC和 DIRECTORY_RINGTONES(传null就是你应用程序的文件目录的根目录)
// 通过指定目录的类型,确保Android的媒体扫描仪将扫描分类系统中的文件(例如,铃声被确定为铃声)
// 如果用户卸载应用程序,这个目录及其所有内容将被删除。
getExternalFilesDir (String type);
File file = new File(getExternalFilesDir(null), "fanrunqi.jpg");
API<8:
//通过该方法打开外存储的根目录,你应该在以下目录下写入你的应用数据,这样当卸载应用程序时该目录及其所有内容也将被删除
getExternalStorageDirectory ();
/Android/data/<package_name>/files/
数据写入:
① 调用Context的openFileOutput()函数,填入文件名和操作模式,它会返回一个FileOutputStream对象。
② 通过FileOutputStream对象的write()函数写入数据。
③ FileOutputStream对象的close ()函数关闭流。
代码:
数据读取:
① 调用openFileInput( ),参数中填入文件名,会返回一个FileInputStream对象。
代码:
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
File sdCardDir = Environment.getExternalStorageDirectory();//获取SDCard目录 "/sdcard"
File saveFile = new File(sdCardDir,"save.txt");
//写数据
try {
FileOutputStream fos= new FileOutputStream(saveFile);
fos.write("happy".getBytes());
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
//读数据
try {
FileInputStream fis= new FileInputStream(saveFile);
int len =0;
byte[] buf = new byte[1024];
StringBuffer sb = new StringBuffer();
while((len=fis.read(buf))!=-1){
sb.append(new String(buf, 0, len));
}
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
//亦可在 /Android/data/package_name/cache/目录下做外部缓存。
3.SQLite数据库存储
Activites 可以通过 Content Provider 或者 Service 访问一个数据库。
数据库创建:
Android 不自动提供数据库。
在 Android 应用程序中使用 SQLite,必须自己创建数据库,然后创建表、索引,填充数据。
Android 提供了 SQLiteOpenHelper 帮助创建数据库,只要继承 SQLiteOpenHelper 类根据开发应用程序的需要,封装创建和更新数据库使用的逻辑就行了。
自己写一个DataBaseHelper类:
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/**
* Created by THF on 17/4/5.
*/
public class DataBaseHelper extends SQLiteOpenHelper {
/**
* @param context 上下文环境(例如,一个Activity)
* @param name 数据库名字
* @param factory 一个可选的游标工厂(通常是 Null)
* @param version 数据库模型版本的整数
* 会调用父类 SQLiteOpenHelper的构造函数
*/
public DataBaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
/**
*在数据库第一次创建的时候会调用这个方法
*根据需要对传入的SQLiteDatabase 对象填充表和初始化数据。
*/
@Override
public void onCreate(SQLiteDatabase db) {
}
/**
* 当数据库需要修改的时候(两个数据库版本不同),Android系统会主动的调用这个方法。
* 一般我们在这个方法里边删除数据库表,并建立新的数据库表.
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//三个参数,SQLiteDatabase 对象,旧版本号,新版本号
}
@Override
public void onOpen(SQLiteDatabase db) { // 每次成功打开数据库后首先被执行
super.onOpen(db);
}
}
继承SQLiteOpenHelper之后就拥有了以下两方法:
- getReadableDatabase() 创建或者打开一个查询数据库
- getWritableDatabase() 创建或者打开一个可写数据库
/**
* 这段代码会返回一个 SQLiteDatabase 类的实例,使用这个对象可以查询、修改数据库
*/
DatabaseHelper database = new DatabaseHelper(context);//传入上下文参数
SQLiteDatabase sqLiteDatabase = null;
sqLiteDatabase = database.getWritableDatabase();
SQLiteDatabase类常用的方法:
/**
* 各参数说明:
table:表名称
colums:列名称数组
selection:条件子句,相当于where
selectionArgs:条件语句的参数数组
groupBy:分组
having:分组条件
orderBy:排序类
limit:分页查询的限制
Cursor:返回值,相当于结果集ResultSet
*/
添加数据行:
更新数据行:
(
long) insert(String table,String nullColumnHack,ContentValues values)
(
int) update(String table, ContentValues values, String whereClause, String[] whereArgs)
删除数据行:
(int) delete(String table,String whereClause,String[] whereArgs)
关闭数据库:
(void) close()
执行一个SQL语句,可以是一个select或其他的sql语句:
(void) execSQL(String sql)
查询指定的数据表返回一个带游标的数据集:
(Cursor) query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
创建表和索引
/**
为了创建表和索引,需要调用 SQLiteDatabase 的 execSQL() 方法来执行 DDL 语句。如果没有异常,这个方法没有返回值。
例如,你可以执行如下代码:
这条语句会创建一个名为 user的表,表有一个列名为 _id,并且是主键,这列的值是会自动增长的整数。
另外还有两列:username( 字符 ) 和 password( 字符 )。 SQLite 会自动为主键列创建索引。
通常情况下,第一次创建数据库时创建了表和索引。要 删除表和索引,需要使用 execSQL() 方法调用 DROP INDEX 和 DROP TABLE 语句。
*/
sqLiteDatabase.execSQL("CREATE TABLE user(_id INTEGER PRIMARY KEY
AUTOINCREMENT, username TEXT, password TEXT);");
增:(2种)
//1.可以使用 execSQL() 方法执行 INSERT, UPDATE, DELETE 等语句来更新表的数据。execSQL() 方法适用于所有不返回结果的 SQL 语句。
String sql = "insert into user(username,password) values ('smile','88888888');//插入操作的SQL语句
sqLiteDatabase.execSQL(sql);//执行SQL语句
//2.使用 SQLiteDatabase 对象的 insert()
ContentValues cv = new ContentValues();
cv.put("username","smile");//添加用户名
cv.put("password","88888888"); //添加密码
sqLiteDatabase.insert("user",null,cv);//执行插入操作
删:
//1.使用SQLiteDatabase 对象的delete()方法。
String whereClause = "username=?";//删除的条件
String[] whereArgs = {"smile"};//删除的条件参数
sqLiteDatabase.delete("user",whereClause,whereArgs);//执行删除
//2.使用execSQL方式的实现
String sql = "delete from user where username=\"smile\""; //删除操作的SQL语句
sqLiteDatabase.execSQL(sql);//执行删除操作
改:
//1.使用SQLiteDatabase 对象的 update()方法。
ContentValues cv = new ContentValues();
cv.put("password","666888");//添加要更改的字段及内容
String whereClause = "username=?";//修改条件
String[] whereArgs = {"smile"};//修改条件的参数
sqLiteDatabase.update("user",cv,whereClause,whereArgs);//执行修改
/**
* 该方法四个参数:
表名;
列名和值的 ContentValues 对象;
可选的 WHERE 条件;
可选的填充 WHERE 语句的字符串,这些字符串会替换 WHERE 条件中的“?”标记,update() 根据条件,更新指定列的值.
*/
//2.使用execSQL方式的实现
String sql = "update [user] set password = '666888' where username=\"smile\"";//修改的SQL语句
sqLiteDatabase.execSQL(sql);//执行修改
查:
/**
* 这段代码会返回一个 SQLiteDatabase 类的实例,使用这个对象可以查询、修改数据库
*/
DatabaseHelper database = new DatabaseHelper(context);//传入上下文参数
SQLiteDatabase sqLiteDatabase = null;
sqLiteDatabase = database.getWritableDatabase();
//1.使用 rawQuery() 直接调用 SELECT 语句
Cursor cursor = sqLiteDatabase.rawQuery("select * from user where username=?",new String[]{"smile"});
if(cursor.moveToFirst()) {
String password = cursor.getString(cursor.getColumnIndex("password"));
}
/**
* 返回值是一个 cursor 对象,这个对象的方法可以迭代查询结果。
* 如果查询是动态的,使用这个方法就会非常复杂。
* 例如,当你需要查询的列在程序编译的时候不能确定,这时候使用 query() 方法会方便很多。
*/
//2.通过query实现查询
/**
* query() 方法用 SELECT 语句段构建查询。
SELECT 语句内容作为 query() 方法的参数,
比如:要查询的表名,要获取的字段名,WHERE 条件,包含可选的位置参数,去替代 WHERE 条件中位置参数的值,GROUP BY 条件,HAVING 条件。
除了表名,其他参数可以是 null。所以代码可写成:
*/
Cursor cursor = sqLiteDatabase.query("user",null,null,null,null,null,null);//查询并获得游标
if(cursor.moveToFirst()){//判断游标是否为空
for(int i=0;i<c.getCount();i++){
cursor.move(i);//移动到指定记录
String username = cursor.getString(c.getColumnIndex("username");
String password = cursor.getString(c.getColumnIndex("password"));
}
}
游标:
执行查询时都会返回一个 Cursor,此为 Android 的 SQLite 数据库游标,使用此游标可以:
getCount() 方法得到结果集中有多少记录;
moveToFirst(), moveToNext(), 和 isAfterLast() 方法遍历所有记录;
getColumnNames() 得到字段名;
getColumnIndex() 转换成字段号;
getString(),getInt() 等方法得到给定字段当前记录的值;
requery() 方法重新执行查询得到游标;
close() 方法释放游标资源;
//代码遍历 user表:
Cursor result= sqLiteDatabase.rawQuery("SELECT _id, username, password FROM user");
result.moveToFirst();
while (!result.isAfterLast()) {
int id=result.getInt(0);
String name=result.getString(1);
String password =result.getString(2);
// do something useful with these
result.moveToNext();
}
result.close();
4.ContentProvider
ContentProvider(内容提供者)是Android的四大组件之一,管理android以结构化方式存放的数据,以相对安全的方式封装数据(表)并且提供简易的处理机制和统一的访问接口供其他程序调用。
有时候我们需要操作其他应用程序的一些数据,就会用到ContentProvider。而且Android为常见的一些数据提供了默认的ContentProvider(包括音频、视频、图片和通讯录等)。
但注意ContentProvider它也只是一个中间人,真正操作的数据源可能是数据库,也可以是文件、xml或网络等其他存储方式。
URI android中:content://(schema) 主机名(Authority) 对象集合 特定的记录(path)
1Android 两个操作URI的工具类
1.1 ContentUris
追加id
Uri uri = Uri.parse("content://cn.sdu.demo/user");
Uri resultUri = ContentUris.withAppendedId(uri, 6);
获取id
Uri uri = Uri.parse("content://cn.sdu.demo/user/6");
long personid = ContentUris.parseId(uri);
1.2 UriMatcher
UriMacher 是一个文本过滤器,用在contentProvider中帮助过滤 分辨出查询者想要查询哪个数据表
a. 初始化
//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
b. 注册需要的Uri
//USER、USER_ID:int型数据
matcher.addURI("cn.sdu.demo", "user", USER);
matcher.addURI("cn.sdu.demo", "user/#",USER_ID);
c.与已经注册的Urip进行匹配
/*
* 如果操作集合,则必须以vnd.android.cursor.dir开头 * 如果操作非集合,则必须以vnd.android.cursor.item开头 * */
@Override
public String getType(Uri uri) {
Uri uri = Uri.parse("content://" + "cn.sdu.demo" + "/user");
switch(matcher.match(uri)){
case USER:
return "vnd.android.cursor.dir/user";
case USER_ID:
return "vnd.android.cursor.item/user";
}
}
2. ContentProvider的主要方法
/**
ContentProvider创建后 或 打开系统后其它应用第一次访问该ContentProvider时调用。 public boolean onCreate()
外部应用向ContentProvider中添加数据。增 public Uri insert(Uri uri, ContentValues values)
外部应用从ContentProvider删除数据。删 public int delete(Uri uri, String selection, String[] selectionArgs)
外部应用更新ContentProvider中的数据。改 public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs):
供外部应用从ContentProvider中获取数据。 查 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
该方法用于返回当前Url所代表数据的MIME类型。 public String getType(Uri uri)
*/
3.ContentResolver
ContentResolver通过URI查询ContentProvider提供数据
除了URI以外,还必须知道需要获取的数据段名称和数据类型
比如需要获取一个特定记录,必须知道当前记录的ID
ContentResolver的方法:
/**
* public Uri insert(Uri uri, ContentValues values) 增
public int delete(Uri uri, String selection, String[] selectionArgs) 删
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) 改
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 查 */
4.ContentObserver
ContentObserver(内容观察者),目的是观察特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时,便会触发它.
5.网络存储