15天快速入门安卓开发(六)持久化存储技术
作者:互联网
文章目录
六 持久化存储技术
持久化技术则提供了一种机制可以让数据在瞬时状态和持久状态之间进行转换。我们常见的有三种,文件存储,即文件存储、SharedPreferences存储以及数据库存储
6.1 文件存储
文件存储是Android中最基本的一种数据存储方式,它不对存储的内容进行任何的格式化处理,所有数据都是原封不动地保存到文件当中的,因而它比较适合用于存储一些简单的文本数据或二进制数据。
- 存储数据
/**
* 文件存储
* @param view
*/
public void save(View view){
FileOutputStream outputStream=null;
BufferedWriter writer=null;
String data = editText.getText().toString();
try {
//Context.MODE_PRIVATE 先建文件,Context.MODE_APPEND追加
outputStream=openFileOutput("data",Context.MODE_PRIVATE );
writer=new BufferedWriter(new OutputStreamWriter(outputStream));
writer.write(data);
}catch (Exception e){
e.printStackTrace();
}finally {
if(writer!=null){
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
- 文件读取
/**
* 加载数据
* @param view
*/
public void load(View view){
FileInputStream fileInputStream=null;
BufferedReader bufferedReader=null;
StringBuilder stringBuilder=new StringBuilder();
try {
fileInputStream=openFileInput("data");
bufferedReader=new BufferedReader(new InputStreamReader(fileInputStream));
String line="";
while((line=bufferedReader.readLine())!=null){
stringBuilder.append(line);
}
Log.d("日志",stringBuilder.toString());
editText.setText(stringBuilder.toString());
editText.setSelection(stringBuilder.toString().length());
}catch (Exception e){
e.printStackTrace();
}finally {
if (bufferedReader!=null){
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Context类中提供的openFileInput()和openFileOutput()方法,之后就是利用Java的各种流来进行读写操作
6.2 SharedPreferences存储
这个其实可以把他理解为键值对存储
我们来一个简单登录与记住密码案例
- 布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/username"
android:orientation="horizontal"
android:layout_centerVertical="true"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="账号:"
android:textSize="30sp"
android:gravity="center"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/account"
android:hint="请输入账号"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/password"
android:orientation="horizontal"
android:layout_below="@id/username"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="密码:"
android:textSize="30sp"
android:gravity="center"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/pwd"
android:hint="请输入密码"
android:inputType="textPassword"
/>
</LinearLayout>
<CheckBox
android:layout_below="@id/password"
android:id="@+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="记住密码" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="登录"
android:layout_below="@id/checkBox"
android:layout_centerHorizontal="true"
android:onClick="login"
/>
</RelativeLayout>
- 代码编写
package com.shu;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
public class SharedPreferencesActivity extends AppCompatActivity {
private EditText username;
private EditText password;
private Button button;
private CheckBox checkBox;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shared_preferences);
SharedPreferences preferences = this.getSharedPreferences( "data", Context.MODE_PRIVATE );
String usernames = preferences.getString("username", "");
Log.d("日志",usernames);
String passwords = preferences.getString("password", "");
Log.d("日志",passwords);
boolean remeber = preferences.getBoolean("remeber", false);
Log.d("日志", String.valueOf(remeber));
if(remeber){
EditText editText = (EditText) findViewById(R.id.account);
editText.setText(usernames);
EditText editText1 = (EditText) findViewById(R.id.pwd);
editText1.setText(passwords);
CheckBox view = (CheckBox) findViewById(R.id.checkBox);
view.setChecked(remeber);
}
}
/**
* 登录
* @param view
*/
public void login(View view){
username= findViewById(R.id.account);
password=findViewById(R.id.pwd);
checkBox=findViewById(R.id.checkBox);
SharedPreferences.Editor editor=getSharedPreferences("data",MODE_PRIVATE).edit();
editor.putString("username",username.getText().toString());
editor.putString("password",password.getText().toString());
editor.putBoolean("remeber",checkBox.isChecked());
editor.apply();
}
}
6.3 数据库存储
SQLite是一款轻量级的关系型数据库,它的运算速度非常快,占用资源很少,通常只需要几百KB的内存就足够了,因而特别适合在移动设备上使用。SQLite不仅支持标准的SQL语法,还遵循了数据库的ACID事务,所以只要你以前使用过其他的关系型数据库,就可以很快地上手SQLite。
语法
SQLite的语法其实跟Mysql,oracle数据库的语法差不多
数据类型
-
NULL: 这个值为空值
-
VARCHAR(n):长度不固定且其最大长度为 n 的字串,n不能超过 4000。
-
CHAR(n):长度固定为n的字串,n不能超过 254。
-
INTEGER: 值被标识为整数,依据值的大小可以依次被存储为1,2,3,4,5,6,7,8.
-
REAL: 所有值都是浮动的数值,被存储为8字节的IEEE浮动标记序号.
-
TEXT: 值为文本字符串,使用数据库编码存储(TUTF-8, UTF-16BE or UTF-16-LE).
-
BLOB: 值是BLOB数据块,以输入的数据格式进行存储。如何输入就如何存储,不改 变格式。
-
DATA :包含了 年份、月份、日期。
-
TIME: 包含了 小时、分钟、秒
常用API
方法名称 | 方法表示含义 |
---|---|
openOrCreateDatabase(String path,SQLiteDatabase.CursorFactory factory) | 打开或创建数据库 |
insert(String table,String nullColumnHack,ContentValues values) | 插入一条记录 |
delete(String table,String whereClause,String[] whereArgs) | 删除一条记录 |
query(String table,String[] columns,String selection,String[] selectionArgs,String groupBy,String having,String orderBy) | 查询一条记录 |
update(String table,ContentValues values,String whereClause,String[] whereArgs) | 修改记录 |
execSQL(String sql) | 执行一条SQL语句 |
close() | 关闭数据库 |
- 创建数据库
db=SQLiteDatabase.openOrCreateDatabase("/data/data/com.lingdududu.db/databases/stu.db",null);
- 创建表
private void createTable(SQLiteDatabase db){
//创建表SQL语句
String stu_table="create table usertable(_id integer primary key autoincrement,sname text,snumber text)";
//执行SQL语句
db.execSQL(stu_table);
}
- 查询
在Android中查询数据是通过Cursor类来实现的,当我们使用SQLiteDatabase.query()方法时,会得到一个Cursor对象,Cursor指向的就是每一条数据。它提供了很多有关查询的方法,具体方法如下:
方法名称 | 方法描述 |
---|---|
getCount() | 获得总的数据项数 |
isFirst() | 判断是否第一条记录 |
isLast() | 判断是否最后一条记录 |
moveToFirst() | 移动到第一条记录 |
moveToLast() | 移动到最后一条记录 |
move(int offset) | 移动到指定记录 |
moveToNext() | 移动到下一条记录 |
moveToPrevious() | 移动到上一条记录 |
getColumnIndexOrThrow(String columnName) | 根据列名称获得列索引 |
getInt(int columnIndex) | 获得指定列索引的int类型值 |
getString(int columnIndex) | 获得指定列缩影的String类型值 |
private void query(SQLiteDatabase db) {
//查询获得游标
Cursor cursor = db.query ("usertable",null,null,null,null,null,null);
//判断游标是否为空
if(cursor.moveToFirst() {
//遍历游标
for(int i=0;i<cursor.getCount();i++){
cursor.move(i);
//获得ID
int id = cursor.getInt(0);
//获得用户名
String username=cursor.getString(1);
//获得密码
String password=cursor.getString(2);
//输出用户信息 System.out.println(id+":"+sname+":"+snumber);
}
}
}
- 插入
private void insert(SQLiteDatabase db){
//实例化常量值
ContentValues cValue =new ContentValues();
//添加用户名
cValue.put("sname","xiaoming");
//添加密码
cValue.put("snumber","01005");
//调用insert()方法插入数据
db.insert("stu_table",null,cValue);
}
private void insert(SQLiteDatabase db){
//插入数据SQL语句
String stu_sql="insert into stu_table(sname,snumber) values('xiaoming','01005')";
//执行SQL语句
db.execSQL(sql);
}
- 修改
rivate void update(SQLiteDatabase db) {
//实例化内容值 ContentValues values = new ContentValues();
//在values中添加内容
values.put("snumber","101003");
//修改条件
String whereClause ="id=?";
//修改添加参数
String[] whereArgs={String.valuesOf(1)};
//修改
db.update("usertable",values,whereClause,whereArgs);
}
private void update(SQLiteDatabase db){
//修改SQL语句
String sql ="update stu_table set snumber = 654321 where id = 1";
//执行SQL
db.execSQL(sql);
}
- 删除
private void delete(SQLiteDatabase db) {
//删除条件
String whereClause ="id=?";
//删除条件参数
String[] whereArgs = {String.valueOf(2)};
//执行删除
db.delete("stu_table",whereClause,whereArgs);
}
private void delete(SQLiteDatabase db) {
//删除SQL语句
String sql ="delete from stu_table where _id = 6";
//执行SQL语句
db.execSQL(sql);
}
SQLiteOpenHelper
该类是SQLiteDatabase一个辅助类。这个类主要生成一 个数据库,并对数据库的版本进行管理。当在程序当中调用这个类的方法getWritableDatabase()或者 getReadableDatabase()方法的时候,如果当时没有数据,那么Android系统就会自动生成一个数据库。
package com.shu;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;
import androidx.annotation.Nullable;
/**
* @author shu
* @date 2021/7/20
* @description
*/
public class SqlLiteUtils extends SQLiteOpenHelper {
/**
* sql语句
*/
private static String sql01="create table user(id integer primary key autoincrement,name text,number text)";
private static String sql02="create table book(id integer primary key autoincrement,name text,type text)";
private Context myContext;
/**
* @param context 上下文
* @param name 数据库名
* @param factory 自定义的Cursor
* @param version 版本号
*/
public SqlLiteUtils(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
myContext=context;
}
/**
* 创建数据库
* @param db
*/
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(sql01);
db.execSQL(sql02);
Toast.makeText(myContext,"数据库创建成功",Toast.LENGTH_LONG).show();
}
/**
* 升级数据库
* @param db
* @param oldVersion
* @param newVersion
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table if exists user");
db.execSQL("drop table if exists book");
onCreate(db);
}
}
如何查看Sqlite数据库
- 在SDK的自带的工具包
- cmd
adb shell //运行Linux命令
cd data/data/全类名/databases //进入数据库文件所在文件夹
ls //查看文件
sqlite3 数据库名 //进入数据库
.table //查看所有表
select * from 表名 //查看具体表
6.4 开源框架
官网:https://github.com/guolindev/LitePal
LitePal是一款开源的Android数据库框架,它采用了对象关系映射(ORM)的模式,并将我们平时开发最常用到的一些数据库功能进行了封装,使得不用编写一行SQL语句就可以完成各种建表和増删改查的操作。
- 添加依赖
implementation 'org.litepal.guolindev:core:3.1.1'
基本使用
- 编写实体类
package com.shu.pojo;
import org.litepal.crud.LitePalSupport;
/**
* @author shu
* @date 2021/7/20
* @description
*/
public class Goods extends LitePalSupport {
private String name;
private String prices;
public Goods(String name, String prices) {
this.name = name;
this.prices = prices;
}
public Goods() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrices() {
return prices;
}
public void setPrices(String prices) {
this.prices = prices;
}
@Override
public String toString() {
return "Goods{" +
"name='" + name + '\'' +
", prices='" + prices + '\'' +
'}';
}
}
- 编写xml
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<!--数据库名称-->
<dbname value="goods" />
<!--数据库版本号-->
<version value="1" />
<!--用于设定所有的映射模型,即你定义数据库表的类名路径-->
<list>
<mapping class="com.shu.pojo.Goods" />
</list>
</litepal>
感觉有Mybatis的那味了
- 修改配置文件
好了,基本的配置完成了,我们就可以操作数据库了
package com.shu;
import androidx.appcompat.app.AppCompatActivity;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import com.shu.pojo.Goods;
import org.litepal.LitePal;
import org.litepal.crud.LitePalSupport;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private SQLiteDatabase database;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
database = LitePal.getDatabase();
}
/**
* 创建数据库
* @param view
*/
public void create(View view){
database = LitePal.getDatabase();
}
/**
* 保存方法
* @param view
*/
public void insert(View view){
Goods goods = new Goods("小米", "26");
goods.save();
}
/**
* 查询数据
* @param view
*/
public void query(View view){
List<Goods> list = LitePal.findAll(Goods.class);
for (Goods goods : list) {
System.out.println(goods);
}
}
}
更多用法请参考教程:https://blog.csdn.net/xxdw1992/article/details/104937107/
标签:15,String,安卓,存储技术,db,public,数据库,import,void 来源: https://blog.csdn.net/weixin_44451022/article/details/119208694