SharedPreferences存储
采用键值对的方式将数据存储在一个XML文件中。
用途:主要用于保存应用内用户的一些偏好设置,如应用的音量等等。
数据存储过程
存数据
①获取SharedPreferences对象,有三种方式:
/**
* 第一个参数为文件名称
* 第二个参数为操作模式,常用的为MODE_PRIVATE,表示只有当前应用程序才可以对这个文件进行读写
*/
sharedPreferences = getSharedPreferences("test", MODE_PRIVATE);
/**
* 只接收一个操作模式参数
* 默认将当前活动的类名作为文件名
*/
sharedPreferences = getPreferences(MODE_PRIVATE);
/**
* 参数为上下文对象
* 使用当前应用程序的包名作为前缀来命名文件
*/
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
②调用SharedPreferences对象的edit()方法得到SharedPreferences.Editor对象
SharedPreferences.Editor editor = sharedPreferences.edit();
③向SharedPreferences.Editor对象采用键值对的形式添加数据
editor.putString("name", "shaw");
editor.putInt("age", 21);
editor.putBoolean("student", true);
前三步常用的写法为:
SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
④调用apply()方法提交数据
editor.apply();
取数据
①获取SharedPreferences对象
②调用SharedPreferences对象的getString()、getInt()等方法读取数据
/**
* 第一个参数为对应的键
* 第二个参数为找不到键对应的值时的默认返回值
*/
sharedPreferences.getString("name", "");
sharedPreferences.getInt("age", 0);
sharedPreferences.getBoolean("student", false);
文件存储
内部存储
内部存储即存储在应用程序内部,且文件默认是只能被当前应用所访问的,当卸载应用的时候,对应的内部存储的文件也会被删除。SharedPreferences和SQLite数据库都是存储在内部存储空间上的。
/**
* 保存内部存储中的内容
* 内部存储不需要声明权限
* 使用openFileOutput来打开一个输出流
*/
public void saveInner() {
FileOutputStream fos = null;
String input = inner_et.getText().toString();
try {
fos = openFileOutput("inner.txt", MODE_PRIVATE);
fos.write(input.getBytes());
Toast.makeText(this, "保存到内部存储文件完成", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
//关闭流
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 读取内部存储中的内容
* 使用openFileInput来打开一个输入流
*/
public void showInner() {
FileInputStream fis = null;
try {
fis = openFileInput("inner.txt");
int len = 0;
byte[] buf = new byte[1024];
//只要还没读到文件末尾就一直读取
while ((len = fis.read(buf)) != -1) {
//将byte类型的数组转换为String类型显示
Toast.makeText(this, "读取到了" + new String(buf, 0, len), Toast.LENGTH_SHORT).show();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
执行效果
GIF.gif外部存储
外部存储并非特指sdcard,无论安卓手机上是否有可移动的sdcard,都存在着外部存储空间,因为访问可移动的sdcard或者手机的内置外部存储都是通过相同的api。当手机连接电脑时,电脑可识别的部分一定为外部存储空间。
使用外部存储时要先检验存储介质是否可用
//判断当前sdcard是否可用
if (state.equals(Environment.MEDIA_MOUNTED)) {
Log.i("tag", "当前sdcard可用");
} else if (state.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
Log.i("tag", "当前sdcard只有读取权限");
flag = false;
} else {
Log.i("tag", "当前sdcard不可用");
flag = false;
}
/**
* 使用外部存储保存图片
*/
public void saveImage() {
BufferedOutputStream bos = null;
BufferedInputStream bis = null;
try {
//获取sdcard根路径
File sdPath = Environment.getExternalStorageDirectory();
file = new File(sdPath, "test.jpg");
//读取项目中的图片资源
InputStream is = getResources().openRawResource(R.drawable.orange);
OutputStream os = new FileOutputStream(file);
//使用输入输出缓冲流进行读写操作
bis = new BufferedInputStream(is);
bos = new BufferedOutputStream(os);
int len = 0;
byte[] buf = new byte[1024];
while ((len = bis.read(buf)) != -1) {
//从0开始写到len
bos.write(buf, 0, len);
//刷新操作
bos.flush();
}
Toast.makeText(this, "图片写入完成", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流操作
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 显示图片
*/
public void showImage() {
//从文件中读取图片
Bitmap bitmap = BitmapFactory.decodeFile(file.getPath());
out_image.setImageBitmap(bitmap);
}
对外部存储的操作需要添加权限
<!--添加写入权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
若运行在Android6.0(API 23)及以上的系统中,需要添加动态权限处理
//申请向外部存储写数据的权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE
}, 1);
GIF.gif
常用的缓存路径
Log.d("tag", "路径1 " + this.getCacheDir());
Log.d("tag", "路径2 " + this.getExternalCacheDir());
Log.d("tag", "路径3 " + Environment.getDownloadCacheDirectory());
图片.png
路径1为内部存储缓存
路径2位外部存储缓存
路径3为根目录缓存
SQLite数据库存储
数据库创建
继承SQLiteOpenHelper类并重写onCreate()和onUpgrade()方法
public class MyDatabaseHelper extends SQLiteOpenHelper {
private 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, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
//数据库被创建时执行,只执行一次
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
Toast.makeText(mContext, "Create succeed", Toast.LENGTH_SHORT).show();
}
//数据库版本更新时执行
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
public class MainActivity extends AppCompatActivity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/**
* 第一个参数为context对象
* 第二个参数为数据库名
* 第三个参数为一个自定义的Cursor对象,一般都为null
* 第四个参数为版本号
* 实例化该对象后使用构造方法创建数据库
*/
dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);
Button createDatabase = (Button) findViewById(R.id.create_database);
Button addData = (Button) findViewById(R.id.add_data);
//创建数据库
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//数据库已存在则打开,否则创建
dbHelper.getWritableDatabase();
}
});
插入数据
/**
* 向表中添加数据
*/
addData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/**
* getWritableDatabase()返回一个可对数据库进行读写操作的对象,
* 当数据库不可写入时,将出现异常
*
* getReadableDatabase()返回一个可对数据库进行读写操作的对象,
* 当数据库不可写入时,返回的对象以只读的方式打开数据库
*/
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
/**
* 开始装填第一条数据
*/
values.put("name", "The Da Vinci Code");
values.put("author", "Dan Brown");
values.put("pages", 454);
values.put("price", 16.96);
db.insert("Book", null, values);
更新数据
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("price", 10.99);
db.update("Book", values, "name=?", new String[]{"The Da Vinci Code"});
删除数据
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.delete("Book", "pages>?", new String[]{"500"});
查询数据
SQLiteDatabase db = dbHelper.getWritableDatabase();
/**
* 第一个参数为表名
* 第二个参数指定查询的列名
* 第三个参数指定where约束条件
* 第四个参数为where中的占位符提供具体的值
* 第五个参数指定需要group by的列
* 第六个参数对group by后的结果进一步约束
* 第七个参数指定查询结果的排序方式,ASC由小到大,DESC由大到小
*/
Cursor cursor = db.query("Book", null, null, null, null, null, null);
if (cursor.moveToFirst()) {
do {
//遍历Cursor对象
String name = cursor.getString(cursor.getColumnIndex("name"));
int pages = cursor.getInt(cursor.getColumnIndex("pages"));
} while (cursor.moveToNext());
}
cursor.close();
也可以使用SQL语句完成CRUD操作
db.execSQL("insert into Book(name,author,pages,price) values(?,?,?,?)", new String[]{
"The Da Vinci Code", "Dan Browm", "454", "16.96"
});
db.execSQL("update Book set price=? where name=?", new String[]{
"10.99", "The Da Vinci Code"
});
db.execSQL("delete from Book where pages>?", new String[]{"500"});
db.rawQuery("select * from Book", null);
即除了查询操作使用rawQuery()方法外,其他操作均使用execSQL()方法完成。
Sqlite数据库事务管理
为了保证数据库中的某些操作要么同时执行,要么同时不执行,需要添加数据库事务管理,
db.beginTransaction();
//具体的数据库操作逻辑
db.setTransactionSuccessful();
db.endTransaction();
网友评论