总结《第一行代码》Android学习笔记(六)数据存储
- 数据存储
- 文件存储
- SharedPreferences存储
- 使用SharedPreferences实现记住账号密码功能
- SQLite数据库存储
- adb shell
- 使用SQLiteDatabase或SQL操作数据库
- 使用LitePal操作数据库
数据存储
Android常用的数据持久化方式:文件存储、SharedPreferences存储以及数据库存储。
文件存储
文件保存的数据默认保存在/data/data/packagename/files/中,可通过Android Studio菜单中的View–>Tool Windows–>Device File Explorer中查看数据。
MainActivity:
public class MainActivity extends AppCompatActivity {
private EditText edit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edit = findViewById(R.id.edit);
String inputText = load();
if(!TextUtils.isEmpty(inputText)){//判断inputText是否为null或者空字符串
edit.setText(inputText);
edit.setSelection(inputText.length());
Toast.makeText(this,"Restoring succeeded",Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
String inputText = edit.getText().toString();
save(inputText);
}
public void save(String inputText){//将数据存储到文件
FileOutputStream out = null;
BufferedWriter writer = null;
try {
out = openFileOutput("data", Context.MODE_PRIVATE);
writer = new BufferedWriter(new OutputStreamWriter(out));
writer.write(inputText);
}catch (IOException e){
e.printStackTrace();
}finally {
try {
if (writer != null){
writer.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
public String load(){//获取文件中的数据
FileInputStream in = null;
BufferedReader reader = null;
StringBuilder content = new StringBuilder();
try{
in = openFileInput("data");
reader = new BufferedReader(new InputStreamReader(in));
String line = "";
while ((line = reader.readLine()) != null){
content.append(line);
}
}catch (IOException e){
e.printStackTrace();
}finally {
if (reader != null){
try{
reader.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
return content.toString();
}
}
SharedPreferences存储
SharedPreferences存储的数据默认保存在/data/data/packagename/shared_prefs/中,可以使用File Explorer查看数据。
获取SharedPreferences有三种方法:
(1)Context类中的getSharedPreferences()方法
SharedPreferences pref = getSharedPreferences("data",MODE_PRIVATE);//参数指定存放数据文件的名称和操作模式
(2)Activity类中的getPreferences()方法
SharedPreferences pref = getPreferences(MODE_PRIVATE);//参数指定操作模式
(3)PreferenceManager类中的getDefaultSharedPreferences()方法
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
MainActivity:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button saveData = findViewById(R.id.save_data);
saveData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//发送数据到SharedPreferences中
SharedPreferences.Editor editor = getSharedPreferences("data",MODE_PRIVATE).edit();
editor.putString("name","youyu4");//第一个参数为键,第二个参数为数据的值
editor.putInt("age",22);
editor.putBoolean("married",false);
editor.apply();
}
});
Button restoreData = findViewById(R.id.restore_data);
restoreData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//从SharedPreferences中读取数据
SharedPreferences pref = getSharedPreferences("data",MODE_PRIVATE);
String name = pref.getString("name","");//第一个参数为键,第二个参数为默认值
int age = pref.getInt("age",0);
boolean married = pref.getBoolean("married",false);
Log.d("MainActivity", "name is " + name);
Log.d("MainActivity", "age is " + age);
Log.d("MainActivity", "married is " + married);
}
});
}
}
使用SharedPreferences实现记住账号密码功能
打开之前使用Broadcast实现的登录界面项目,在activity_login中添加一个CheckBox复选框控件,用户可以通过点击的方式来选择是否要记住账号密码。
LoginActivity:
public class LoginActivity extends BaseActivity {
private EditText accountEdit;
private EditText passwordEdit;
private Button login;
private SharedPreferences.Editor editor;
private SharedPreferences pref;
private CheckBox rememberPass;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
accountEdit = findViewById(R.id.account);
passwordEdit = findViewById(R.id.password);
rememberPass = findViewById(R.id.remember_pass);
pref = getSharedPreferences("data",MODE_PRIVATE);
editor = pref.edit();
Boolean isRemember = pref.getBoolean("isRemember",false);
if(isRemember){
//将账号和密码都设置到文本框中
accountEdit.setText(pref.getString("account",""));
passwordEdit.setText(pref.getString("password",""));
rememberPass.setChecked(true);
}
login = findViewById(R.id.login);
login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String account = accountEdit.getText().toString();
String password = passwordEdit.getText().toString();
if(account.equals("admin")&&password.equals("123456")){
if (rememberPass.isChecked()){//检查复选框是否被选中
editor.putString("account",account);
editor.putString("password",password);
editor.putBoolean("isRemember",true);
}else{
editor.clear();
}
editor.apply();
Intent intent = new Intent(LoginActivity.this,MainActivity.class);
startActivity(intent);
finish();
}else{
Toast.makeText(LoginActivity.this,"account or password is invalid",Toast.LENGTH_SHORT).show();
}
}
});
}
}
SQLite数据库存储
adb shell
存储的文件默认保存在/data/data/packagename/databases/中,无法使用File Explorer查看数据库中的数据,因此使用adb shell来查看数据。首先将platform-tools目录配置进系统环境变量中,然后打开命令行界面输入"adb shell",若符号为"$“则证明为普通管理员,无法查看数据库,输入命令"su"后符号变为”#“并成为超级管理员(注意安卓虚拟机7.0级7.0以上版本无法设置超级管理员权限,因此使用Android7.0以下的虚拟器运行项目)然后输入"cd"命令进入/data/data/packagename/databases/数据库目录下输入"ls"可以看到BookStore.db,然后输入"sqlite3 BookStore.db"进入数据库,输入”.table"命令可以看数据库有哪些表,输入".schema"命令可以查看建表语句,输入"select * from Book;"命令可以查询Book表的数据。
使用SQLiteDatabase或SQL操作数据库
新建MyDatabaseHelper类继承自SQLiteOpenHelper:
public class MyDatabaseHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK = "create table Book ("
+"id integer primary key autoincrement,"
+"author text,"
+"price real,"
+"pages integer,"
+"name text)";
public static final String CREATE_CATEGORY = "create table Category ("
+"id integer primary key autoincrement,"
+"category_name text,"
+"category_code integer)";
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);
db.execSQL(CREATE_CATEGORY);
//Toast.makeText(mContext,"Create succeeded",Toast.LENGTH_SHORT).show();
}
//更新数据库
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table if exists Book");
db.execSQL("drop table if exists Category");
onCreate(db);
}
}
新建布局包含增删改查四个按钮,并修改MainActivity.java:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new MyDatabaseHelper(this,"BookStore.db",null,7);
Button createDatabase = findViewById(R.id.create_database);
Button addData = findViewById(R.id.add_data);
Button updateData = findViewById(R.id.update_data);
Button deleteData = findViewById(R.id.delete_data);
Button queryData = findViewById(R.id.query_data);
//新建数据库
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dbHelper.getWritableDatabase();
}
});
//增
addData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
//SQLiteDatabase操作
// ContentValues values = new ContentValues();
// values.put("name","aaa");
// values.put("author","qmt");
// values.put("pages",666);
// values.put("price",233.33);
// db.insert("Book",null,values);
// values.clear();
// values.put("name","bbb");
// values.put("author","sxm");
// values.put("pages",777);
// values.put("price",2333.33);
// db.insert("Book",null,values);
//SQL操作
db.execSQL("insert into Book (name,author,pages,price)values(?,?,?,?)",new String[]{"aaa","qmt","666","233.33"});
db.execSQL("insert into Book (name,author,pages,price)values(?,?,?,?)",new String[]{"bbb","sxm","777","2333.33"});
}
});
//改
updateData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
//SQLiteDatabase操作
// ContentValues values = new ContentValues();
// values.put("price",10.99);
// db.update("Book",values,"name = ?",new String[] {"aaa"});
//SQL操作
db.execSQL("update Book set price = ? where name = ?",new String[] {"10.99","aaa"});
}
});
//删
deleteData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
//SQLiteDatabase操作
// db.delete("Book","name = ?",new String[] {"bbb"});
//SQL操作
db.execSQL("delete from Book where name = ?",new String[] {"bbb"});
}
});
//查
queryData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
//SQLiteDatabase操作
// Cursor cursor = db.query("Book",null,null,null,null,null,null);
//SQL操作
Cursor cursor = db.rawQuery("select * from Book",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(TAG, "name: " + name + ",author: " + author + ",pages:" + pages + ",price:" + price);
}while(cursor.moveToNext());
}
cursor.close();
}
});
}
}
使用LitePal操作数据库
首先在build.gradle中添加依赖库:
implementation 'org.litepal.android:java:3.0.0'
然后在app/src/main中新建assets目录并新建litepal.xml文件,dbname是数据库名,version是数据库版本号,list为指定的映射模型,,添加Book类和Category类:
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<dbname value="BookStore" />
<version value="2" />
<list>
<mapping class="com.example.youyu4.litepaltest.Book"></mapping>
<mapping class="com.example.youyu4.litepaltest.Category"></mapping>
</list>
</litepal>
在AndroidManifest中配置LitePalApplication:
<application
android:name="org.litepal.LitePalApplication"
...
...>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
因为LitePal采取的是面向对象映射(ORM)模式,因此定义Book类:
public class Book extends LitePalSupport {
private int id;
private String author;
private String name;
private double price;
private int pages;
private String press;
//Getter和Setter
...
}
Category类:
public class Category {
private int id;
private String categoryName;
private int categoryCode;
public void setId(int id) {
this.id = id;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public void setCategoryCode(int categoryCode) {
this.categoryCode = categoryCode;
}
}
MainActivity.java:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button createDatabase = findViewById(R.id.create_database);
Button addData = findViewById(R.id.add_data);
Button updateData = findViewById(R.id.update_data);
Button deleteData = findViewById(R.id.delete_data);
Button queryData = findViewById(R.id.query_data);
//创建数据库
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
LitePal.getDatabase();
}
});
//使用LitePal进行数据操作
// 增
addData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Book book = new Book();
book.setName("aaa");
book.setAuthor("qmt");
book.setPages(666);
book.setPrice(233.33);
book.setPress("Unknow");
book.save();
}
});
//改
updateData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Book book = new Book();
book.setPrice(14.95);
book.setPress("Anchor");
// book.setToDefault("pages");//更新数据为默认值
book.updateAll("name = ?","aaa");
}
});
//删
deleteData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
LitePal.deleteAll(Book.class,"price < ?","15");
}
});
//查
queryData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
List<Book> books = LitePal.findAll(Book.class);
for(Book book: books){
Log.d(TAG, "name: " + book.getName() + ",author: " + book.getAuthor() + ",pages:" + book.getPages() + ",price:" + book.getPrice() + ",press:" + book.getPress());
}
}
});
}
}