前言
学完了第一行代码的第六章,在这里做一个简单的总结。
一.文件储存
文件储存主要运用Context类提供的openFileInput,和openFileOutput方法和java中的io流进行交汇,完成数据储存
注意这里用到了io流,一定要对其进行异常处理
若要查看文件保存的地方,在打开虚拟机时点击右下角竖着的Device File Explorer,找到/data/data/包名/Files,我们写的文件就储存在这里
写文件
private void save() {
String data = editText.getText().toString();
// Log.d("MainActivity",data);
FileOutputStream fos = null;
BufferedWriter bw = null;
try{
fos = openFileOutput("data", Context.MODE_PRIVATE);
bw = new BufferedWriter(new OutputStreamWriter(fos));
bw.write(data);
}catch (IOException o){
o.printStackTrace();
}finally {
try{
if(bw!=null)
bw.close();
}catch (IOException o){
o.printStackTrace();
}
}
}
读文件
private String Load() {
FileInputStream fis = null;
BufferedReader br = null;
StringBuilder data = new StringBuilder();
try{
fis = openFileInput("data");
br = new BufferedReader(new InputStreamReader(fis));
String line = "";
while( (line = br.readLine())!=null )
data.append(line);
}catch (IOException o){
o.printStackTrace();
}finally {
try{
if(br!=null)
br.close();
}catch (IOException o){
o.printStackTrace();
}
}
return data.toString();
}
看一个完整的例子,读出EditText中写的字符串储存在data文件中,下次打开时直接在EditText的编辑区出现(注意:直接关闭虚拟机不会执行onDestroy(),要点左下角的退出)
package com.example.revise_file;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.widget.EditText;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class MainActivity extends AppCompatActivity {
private EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText)findViewById(R.id.edittext);
String data = Load();
if(!TextUtils.isEmpty(data)){
editText.setText(data);
editText.setSelection(data.length()); //设置光标到末尾
}
}
private String Load() {
FileInputStream fis = null;
BufferedReader br = null;
StringBuilder data = new StringBuilder();
try{
fis = openFileInput("data");
br = new BufferedReader(new InputStreamReader(fis));
String line = "";
while( (line = br.readLine())!=null )
data.append(line);
}catch (IOException o){
o.printStackTrace();
}finally {
try{
if(br!=null)
br.close();
}catch (IOException o){
o.printStackTrace();
}
}
return data.toString();
}
@Override
protected void onDestroy() {
super.onDestroy();
// Log.d("MainActivity")
save();
}
private void save() {
String data = editText.getText().toString();
// Log.d("MainActivity",data);
FileOutputStream fos = null;
BufferedWriter bw = null;
try{
fos = openFileOutput("data", Context.MODE_PRIVATE);
bw = new BufferedWriter(new OutputStreamWriter(fos));
bw.write(data);
}catch (IOException o){
o.printStackTrace();
}finally {
try{
if(bw!=null)
bw.close();
}catch (IOException o){
o.printStackTrace();
}
}
}
}
二.SharedPreferences储存
SharedPreferences储存是使用键值对的方式来储存数据的,储存时每一个数据对应一个键,读取时通过键读取值。
若要查看文件保存的地方,在打开虚拟机时点击右下角竖着的Device File Explorer,找到/data/data/包名/shared_prefs,我们写的文件就储存在这里
写文件
在获取Sharedpreferences对象时,有三种获取方法
1.Context类提供的getSharedPreferences()方法,传入两个参数,第一个是文件名,第二个是操作模式,MODE_PRIVATE表示只有当前的应用程序可对其读写
2.Activity类的getSharedPreferences()方法,接收一个操作模式的参数,吧活动的类名当做文件名
3.PreferenceManger类中的getDefaultSharedPreferences()方法,静态方法,用包名作为前缀名来命名文件,接收一个Context参数
private void save() {
String data = editText.getText().toString();
//第一步:获取Sharedpreferences对象
SharedPreferences sharedPreferences = getSharedPreferences("data",MODE_PRIVATE);
//第二步:获取SharedPreferences.Editor对象
SharedPreferences.Editor editor = sharedPreferences.edit();
//第三步,添加数据
editor.putString("data",data);
//第四步:提交
editor.apply();
}
读文件
private String Load() {
//第一步:创建SharedPreferences 类型对象
SharedPreferences sharedPreferences = getSharedPreferences("data",MODE_PRIVATE);
//第二步:获取
String data = sharedPreferences.getString("data","");
return data;
}
完整的例子
package com.example.revice_sharedpreferences;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.TextUtils;
import android.widget.EditText;
public class MainActivity extends AppCompatActivity {
private EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText)findViewById(R.id.edittext);
String data = Load();
if(!TextUtils.isEmpty(data)){
editText.setText(data);
editText.setSelection(data.length()); //设置光标到末尾
}
}
private String Load() {
//第一步:创建SharedPreferences 类型对象
SharedPreferences sharedPreferences = getSharedPreferences("data",MODE_PRIVATE);
//第二步:获取
String data = sharedPreferences.getString("data","");
return data;
}
@Override
protected void onDestroy() {
super.onDestroy();
save();
}
private void save() {
String data = editText.getText().toString();
//第一步:获取Sharedpreferences对象
SharedPreferences sharedPreferences = getSharedPreferences("data",MODE_PRIVATE);
//第二步:获取SharedPreferences.Editor对象
SharedPreferences.Editor editor = sharedPreferences.edit();
//第三步,添加数据
editor.putString("data",data);
//第四步:提交
editor.apply();
}
}
三.新控件CheckBox
书中的demo中出现了一个新的控件在这里提一提
继承关系
kotlin.Any
↳ android.view.View
↳ android.widget.TextView
↳ android.widget.Button
↳ android.widget.CompoundButton
↳ android.widget.CheckBox
主要函数
isChecked() //确定是否选中;
setChecked(bool checked) //设置选中或取消选中;
监听事件
checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// TODO Auto-generated method stub
if(isChecked){
editText1.setText(buttonView.getText()+"选中");
}else{
editText1.setText(buttonView.getText()+"取消选中");
}
}
});
四.数据库储存
这里提供了两种操作SQLite数据库的方法,第一种SQLite数据库存储,第二种LitePal。
SQLite数据库存储
1.创建数据库
Android为了能更好更方便的管理数据库,专门提供了一个SQLiteOpenHelper帮助类,借助这个类可完成对数据库的创建和升级。
创建自己的帮助类
public class MySQLiteOPenHelper extends SQLiteOpenHelper {
//写建表语句
public static final String CREATR_BOOK ="create table Book(" +
"id integer primary key autoincrement,"
//将id设为主键,并用autoincrement关键字表示id列自增长
+ "author text," // text文本类型
+ "price real," //real 浮点型
+ "pages integer," //integer 整型
+ "name text)"; //blob 二进制型
public static final String CREATE_CATEFORY = "create table Category("+
"id integer primary key autoincrement,"
+"name text,"
+"code integer)";
private Context context;
//有两个构造方法可供重写,一般选择参数少的即可
//参数 第一个:上下文,第二个:数据库名,
//第三个:允许我们在查询数据时返回自定义Cursor,一般传入null
//第四个:当前的版本号
public MySQLiteOPenHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
this.context = context;
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL(CREATR_BOOK);
//这个方法用于创建表
sqLiteDatabase.execSQL(CREATE_CATEFORY);
Toast.makeText(context,"create success",Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
sqLiteDatabase.execSQL("drop table if exists Book");
sqLiteDatabase.execSQL("drop table if exists Category");
onCreate(sqLiteDatabase);
}
}
实例化帮助类
MySQLiteOPenHelper sqLiteOPenHelper = new
MySQLiteOPenHelper(this,"BookStore.db",null,1);
创建数据库
//这两个方法都表示创建或打开一个现有的数据库
sqLiteOPenHelper.getWritableDatabase();
//sqLiteOPenHelper.getReadableDatabase()
2.升级数据库
在SQLiteOPenHelper帮助类直接改写要升级的地方,如添加表,修改表列等
吧创建类实例时的版本号加1(版本号加一后会回调onUpgrade()方法)
sqLiteOPenHelper = new
MySQLiteOPenHelper(this,"BookStore.db",null,2);
在onUpgrade()中通过DROP语句删除原来存在的表,并调用onStart()方法(如果直接调用onStart()方法,原来表存在,在创建时直接报错)
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
sqLiteDatabase.execSQL("drop table if exists Book");
sqLiteDatabase.execSQL("drop table if exists Category");
onCreate(sqLiteDatabase);
}
3.添加数据
添加数据主要调用SQLiteDatabase的insert方法,此方法接收三个参数,
第一个是表名
第二个参数用于在未指定添加数据的情况下给某些可为空的列自动赋值null,一般用不到这个方法,直接传入null,
第三个参数是ContentValues对象,用于存放添加的数据
//获取SQLiteDatabase对象
SQLiteDatabase db = sqLiteOPenHelper.getReadableDatabase();
//获取ContentValues对象,存放数据
ContentValues values = new ContentValues();
values.put("name","123");
values.put("pages",234);
values.put("price",16);
values.put("author","Day");
db.insert("Book",null,values);
values.clear(); //如果要再次组装数据,需要把values清空
values.put("name","aaa");
values.put("pages",12);
values.put("price",230);
values.put("author","god");
db.insert("Book",null,values);
4.更新数据
更新数据主要调用SQLiteDatabase的update方法,此方法接收四个参数,
第一个是表名
第二个参数是ContentValues对象,用于存放更新的数据
第三,四个参数是用于约束更新某一行或某几行的数据,不指定的话默认更新所有行
SQLiteDatabase sqLiteDatabase = sqLiteOPenHelper.getReadableDatabase();
ContentValues values1 = new ContentValues();
values1.put("price",29);
sqLiteDatabase.update("Book",values1,"name = ?",
new String[]{"123"});
5.删除数据
删除数据主要调用SQLiteDatabase的delete方法,此方法接收三个参数,
第一个是表名
第二,三个参数是用于约束删除某一行或某几行的数据,不指定的话默认更新所有行
SQLiteDatabase sqLiteDatabase1 = sqLiteOPenHelper.getReadableDatabase();
sqLiteDatabase1.delete("Book","name = ?",new String[]{"bbb"});
6.查询数据
查询数据主要调用SQLiteDatabase的query方法,此方法最短的重载接收7个参数
query()方法参数 | 描述 |
table | 指定查询的表名 |
columns | 指定查询的列名 |
selection | 指定where的约束条件 |
selectionArgs | 为where中的占位符提供具体的值 |
groupBy | 指定需要group by的列 |
having | 对group by后的结果进一步约束 |
orderBy | 指定查询结果的排序方法 |
我们在使用时不必为每条语句都指定所有的参数,此方法返回一个CurSor对象,查询到的数据可从这个对象中取出
SQLiteDatabase sqLiteDatabase2 = sqLiteOPenHelper.getReadableDatabase();
//查询所有数据
Cursor cursor = sqLiteDatabase2.query
("Book",null,null,null,null,null,null);
if(cursor.moveToFirst()){ //将数据的指针移动到第一行的位置
do{
//通过Cursor的getColumnIndex()方法获取到某一列在表中对应位置的索引
String name = cursor.getString(cursor.getColumnIndex("name"));
String author = cursor.getString(cursor.getColumnIndex("author"));
String price = cursor.getString(cursor.getColumnIndex("price"));
Log.d("MAinActivity",name+" "+author+" "+price);
}while (cursor.moveToNext());
}
cursor.close();
adb的使用
adb是Android SDK中自带的一个调试工具,使用这个工具可对连接在电脑上的手机或模拟器进行调试操做。
首先要配置环境变量,adb存放在sdk的platfrom-tools目录下,在系统变量中找到Path并把platfrom-tools目录配制进去
使用方法
1. 打开命令行界面,输入adb shell
2.如果显示的是$,需要输入su
3.cd命令进入到数据库存放目录下
比如cd /data/data/com.example.revise_6_2/databases
4. sqlite3 + 数据库名(打开数据库)
比如sqlite3 BookStore.db
之后可进行查看的操作,常见的操作:
操作 | 用途 |
.schema | 查看建表语句 |
.table | 查看有哪些表 |
select * from + 表名;(比如select * from Book;) | 查看数据 |
LitePal操作数据库
LitePal是一个开源库,这里有详细教程用法
关于adb工具在这里不细说,如果配置好无法正常使用,可更换虚拟机试试,我的手机虚拟机就是权限不够要自己root,但是平板一切正常。
配置
1.先在网上找到最新的版本号,点这里获取 往下滑如图吧 implementation 'org.litepal.guolindev:core:3.1.1’添加到build.gradle文件
2.配置litepal.xml文件,在app/src/main/目录下 new ->Directory,创建一个assets目录,再在assets目录先新建litepal.xml文件,内容如下
<?xml version="1.0" encoding="utf-8"?>
<litepal>
/*
dbname定义应用程序的数据库名称。默认情况下,每个数据库名称都应以.db结尾。如果您未使用.db结尾数据库,LitePal会自动为您添加后缀。
version定义数据库的版本
list 指定到所有的映射模型
*/
<dbname value="BookStore"></dbname>
<version value="1"></version>
<list>
</list>
</litepal>
3.在AndroidManifest.xml中配置LitePalApplication
< manifest >
< application
android :name = “ org.litepal.LitePalApplication ”
...
>
...
</ application >
</ manifest >
创建升级数据库
1.创建表(就是创建一个类,表中有什么项就定义什么字段,并生成get,set方法)
public class Book {
private int id;
private String author;
...
public int getId() {
return id;
}
public String getAuthor() {
return author;
}
public void setId(int id) {
this.id = id;
}
public void setAuthor(String author) {
this.author = author;
}
...
}
2.将这些模型添加到litepal.xml的映射列表中:
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<dbname value="BookStore">
</dbname>
<version value="1"></version>
<list>
<mapping class="com.example.litepaltext.Book"></mapping>
</list>
</litepal>
如果要创建多个表重复如上操作
这些表在你下次操作数据库时自动生成。比如点击按钮时代码获取SQLiteDatabase,进行了数据库的操作,自动生成Book表
Button createDatabase = (Button)findViewById(R.id.create_database);
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//SQLiteDatabase db = LitePal.getDatabase();
LitePal.getDatabase();
}
});
3.升级库
修改Book表的代码,变成你想要的,比如添加一个字段
public class Book {
private int id;
private String author;
private int pages;
...
public int getPages() {
return pages;
}
public void setPrice(double price) {
this.price = price;
}
...
}
吧版本号加1
</dbname>
<version value="2"></version>
添加数据
先让我们的表继承LitePalsupport(书中的DataSupport已被弃用,应该为LitePalsupport),当然用熟了在建表时就可直接写出继承
public class Book extends LitePalSupport {
...
}
以下代码完成数据的添加
//第一步:new 对象
Book book1 = new Book();
//第二步:set方法设置数据
book1.setAuthor("aaa");
book1.setName("bbb");
book1.setPages(500);
book1.setPrice(5);
book1.setPress("ujfch");
//第三步:保存
book1.save();
更新数据
updata(),updataAll()
// 法一:
// 对已储存的对象重新设值,重新调用save()方法
/*
Book book = new Book();
book.setAuthor("123");
book.setName("34");
book.setPages(123);
book.setPrice(19);
book.setPress("ujfch");
book.save();
//对于已储存的直接这样更新-
book.setPress("fjkf");
book.save();
*/
// 法二:使用updataAll方法更新整个记录,也可用update()使用指定的ID更新单个记录
Book book1 = new Book();
book1.setPress("Anchor");
book1.setPrice(0);
book.updateAll("name = ? and author = ?","34","123");
对于更新成默认值的应该用如下方法
Book book1 = new Book();
book1.setPress("Anchor");
//book1.setPages(0); //更新成默认值时,用这种方法无效
book1.setToDefault("pages"); //应该用这个方法
book1.setPrice(100);
book1.updateAll("name = ? and author = ?","34","123");
删除数据
delete(),deleteAll()
书上的方法过时,应改为如下
//LitePal.delete(Song.class, id); 删除id对应的
LitePal.deleteAll(Book.class,"pages < ?","15");
查询数据
find(),findAll()
Book book = LitePal.find(Book.class,id);
List<Book> list = LitePal.findAll(Book.class);