经验:1.sqlite表中的类型限定并不起作用,底层所有的数据都是String,为了节约手机内存
2.4.0版本以后数据库在创建时会产生一个临时文件
3.4.4版本以后虚拟机引用了ART模式,使速度更快
4.开发分包示例
1.android下数据库的创建
什么时候使用数据库做数据存储? 有大量具有相同结构的数据需要存储时。
mysql sql2008 sqlite 内置的 轻量级
SqliteOpenHelper:
1.创建一个类继承SqliteOpenHelper,写一个构造方法用来指定数据库的名称版本
2.实现两个方法:
//构造方法 ,用来指定数据库的名称和版本号
public MySqliteOpenHelper(Context context) {
//context :上下文 name: 数据库文件的名称 factory:用来创建cursor对象,默认传null version:数据库的版本,从android4.0之后只能升不能降。
super(context, "info.db", null, 2);
}
onCreate:数据库第一次创建的时候调用onCreate方法, 特别适合做表结构的初始化
//数据库第一次创建的时候调用onCreate方法, 特别适合做表结构的初始化
@Override
public void onCreate(SQLiteDatabase db) {
//做表结构的初始化就需要执行create table这样的sql语句
//使用db执行sql语句
db.execSQL("create table info (_id integer primary key autoincrement ,name varchar(20) )");
}
//当数据库的版本发生改变的时候会调用onUpgrade方法;特别适合做表结构的修改
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//做表结构的修改需要执行sql语句
// db.execSQL("alter table info add phone varchar(20)");
System.out.println("oldVersion:"+oldVersion +" newVersion: "+newVersion);
}
onUpgrade:当数据库的版本发生改变的时候会调用onUpgrade方法;特别适合做表结构的修改
3.创建一个帮助类的实例化对象,并调用getReadableDatabase或getWritableDatabase方法,可以帮助我们创建或打开一个数据库。
*******getReadableDatabase和getWritableDatabase区别:
getReadableDatabase:首先尝试以读写的方式打开数据库,如果磁盘空间满了,会再次尝试以只读方式打开数据库。
getWritableDatabase: 直接以读写方式打开数据库,如果磁盘空间满了,直接报错。
2.Android下数据库的第一种增删改查方法(没有返回值,适合查询使用)
public class InfoDaoUtils {
private MySqliteOpenHelper mySqliteOpenHelper;
public InfoDaoUtils (Context context){
//1.创建帮助类对象
mySqliteOpenHelper = new MySqliteOpenHelper(context);
}
//增加方法
public void insert(UserBean bean){
//执行sql语句需要SqliteDatabase对象
//2.调用getReadableDatabase获取一个SqliteDatabase对象
SQLiteDatabase db = mySqliteOpenHelper.getReadableDatabase();//这个方法不要再构造函数中初始化,不方便数据库操作
//3.执行sql语句 sql:sql语句 bindArgs:?sql语句中占位符的值。
db.execSQL("insert into info(name,phone) values(?,?);", new Object[]{bean.name,bean.phone});
//4.关闭数据库对象
db.close();
}
//删除方法
public void delete(String name){
//执行sql语句需要SqliteDatabase对象
//2.调用getReadableDatabase获取一个SqliteDatabase对象
SQLiteDatabase db = mySqliteOpenHelper.getReadableDatabase();
//3.执行sql语句 sql:sql语句 bindArgs:?sql语句中占位符的值。
db.execSQL("delete from info where name=?;", new Object[]{name});
//4.关闭数据库对象
db.close();
}
//更新方法
public void update(UserBean newuserBean){
//执行sql语句需要SqliteDatabase对象
//2.调用getReadableDatabase获取一个SqliteDatabase对象
SQLiteDatabase db = mySqliteOpenHelper.getReadableDatabase();
//3.执行sql语句 sql:sql语句 bindArgs:?sql语句中占位符的值。
db.execSQL("update info set phone=? where name=?;", new Object[]{newuserBean.phone,newuserBean.name});
//4.关闭数据库对象
db.close();
}
//查询方法
public void query(String name){
//执行sql语句需要SqliteDatabase对象
ArrayList list = new ArrayList();
//2.调用getReadableDatabase获取一个SqliteDatabase对象
SQLiteDatabase db = mySqliteOpenHelper.getReadableDatabase();
//3.执行sql语句 sql:sql语句 selectionArgs:?sql语句中查询条件的占位符的值。 返回一个cursor游标结果集对象
Cursor cursor = db.rawQuery("select name,phone from info where name = ? ", new String[]{name});
//4.获取结果集中的数据封装到list中
if(cursor != null && cursor.getCount() > 0){//说明结果集中有数据
while(cursor.moveToNext()){//游标可以指向下一行
//解析一行数据
String name_str = cursor.getString(cursor.getColumnIndex("name"));//通过获取字段编号再获得字段值,不会弄错编号
String phone_str = cursor.getString(cursor.getColumnIndex("phone"));
System.out.println("name : "+name_str + " phone:"+phone_str);
UserBean userBean = new UserBean();
userBean.name = name_str;
userBean.phone = phone_str;
list.add(userBean);
}
//关闭游标对象
cursor.close();
}
//5.关闭数据库对象
db.close();
}
3.Android下另一种增删改查(谷歌封装的API,有返回值,适合增删改)
public class InfoDaoUtils2 {
private MySqliteOpenHelper mySqliteOpenHelper;
public InfoDaoUtils2 (Context context){
//1.创建帮助类对象
mySqliteOpenHelper = new MySqliteOpenHelper(context);
}
//增加方法
public boolean insert(UserBean bean){
//执行sql语句需要SqliteDatabase对象
//2.调用getReadableDatabase获取一个SqliteDatabase对象
SQLiteDatabase db = mySqliteOpenHelper.getReadableDatabase();
// db.execSQL("insert into info(name,phone) values(?,?);", new Object[]{bean.name,bean.phone});
ContentValues values = new ContentValues();//底层封装的是一个map
values.put("name", bean.name);
values.put("phone", bean.phone);
//3.执行sql语句
//table: 表名 nullColumnHack:可以为null values:封装要添加的列的值 返回值:新添加这一行的行的id,如果是-1标示添加失败
long result = db.insert("info", null, values);
//4.关闭数据库对象
db.close();
if(result == -1){
return false;
}else{
return true;
}
}
//删除方法
public int delete(String name){
//执行sql语句需要SqliteDatabase对象
//2.调用getReadableDatabase获取一个SqliteDatabase对象
SQLiteDatabase db = mySqliteOpenHelper.getReadableDatabase();
//3.执行sql语句
//table:表名 whereClause:删除的条件 whereArgs:删除条件占位符的值 返回值:成功删除了多少行
int result = db.delete("info", "name=?", new String []{name});
//4.关闭数据库对象
db.close();
return result;
}
//更新方法
public int update(UserBean newuserBean){
//执行sql语句需要SqliteDatabase对象
//2.调用getReadableDatabase获取一个SqliteDatabase对象
SQLiteDatabase db = mySqliteOpenHelper.getReadableDatabase();
//3.执行sql语句
ContentValues values = new ContentValues();
values.put("phone", newuserBean.phone);
//table: values:要更新的列 whereClause:更新条件 whereArgs:更新条件占位符的值 返回值:成功修改了多少行
int result = db.update("info", values, "name=?", new String[]{newuserBean.name});
//4.关闭数据库对象
db.close();
return result;
}
//查询方法
public void query(String name){
//执行sql语句需要SqliteDatabase对象
ArrayList list = new ArrayList();
//2.调用getReadableDatabase获取一个SqliteDatabase对象
SQLiteDatabase db = mySqliteOpenHelper.getReadableDatabase();
//3.执行sql语句
//table :表名 columns:查询哪些列 ,如果传null代表查询所有列 selection:查询的条件 selectionArgs:条件占位符的值 groupBy:按什么分组 having:分组的条件 orderBy :按什么排序
Cursor cursor = db.query("info", new String[]{"name","phone"}, "name = ?", new String[]{name}, null, null, "_id desc");
//4.获取结果集中的数据封装到list中
if(cursor != null && cursor.getCount() > 0){//说明结果集中有数据
while(cursor.moveToNext()){//游标可以指向下一行
//解析一行数据
String name_str = cursor.getString(cursor.getColumnIndex("name"));
String phone_str = cursor.getString(cursor.getColumnIndex("phone"));
System.out.println("name : "+name_str + " phone:"+phone_str);
UserBean userBean = new UserBean();
userBean.name = name_str;
userBean.phone = phone_str;
list.add(userBean);
}
//关闭游标对象
cursor.close();
}
//5.关闭数据库对象
db.close();
}
}
4.数据库事务(适合银行操作,代码块中同时成功或者同时失败)
1.事务对于查询安全性的作用
//做转账业务,执行sql语句
public void transtationAccount(View v){
AccountSqliteOpenHelper accountSqliteOpenHelper = new AccountSqliteOpenHelper(this);
SQLiteDatabase db = accountSqliteOpenHelper.getReadableDatabase();
//开启事务
db.beginTransaction();
try {
db.execSQL("update account set money= money-200 where name=?",new String[]{"李四"});
//模拟一个异常
int i = 100/0;
db.execSQL("update account set money= money+200 where name=?",new String[]{"张三"});
db.setTransactionSuccessful();//设置一个成功的标记
} finally {
db.endTransaction();//结束事务,要判断事务是否成功,如果成功提交所有sql语句,如果失败,回滚所有的sql语句
}
db.close();
}
2.事务对于提高数据库批量操作效率的作用
在批量修改数据的时候,由于事务是在进行事务提交时将要执行的SQL操作一次性打开数据库连接执行,其执行速度比逐条执行SQL语句的速度快了很多倍。因此当我们开发中遇到对数据库的批量操作那么,使用事务是提高效率的重要原则。
publicvoidtestTransactionEfficient(){
PersonOpenHelper helper =newPersonOpenHelper(getContext(),"person",null, 2);
SQLiteDatabase database = helper.getWritableDatabase();
// ------测试不使用事务时插入1w条数据耗时--------------------
longbeginTime = System.currentTimeMillis();
for(inti=0;i<10000;i++){
database.execSQL("insert into person(name,age,phone) values('text'+"+i+","+i+",'"+(1320000+i)+""+"')");
}
longendTime = System.currentTimeMillis();
System.out.println("不使用事务插入1w条数据耗时:"+(endTime-beginTime)+"毫秒");
// ---------测试使用事务时耗时-----------------------
beginTime = System.currentTimeMillis();
database.beginTransaction();
for(inti=0;i<10000;i++){
database.execSQL("insert into person(name,age,phone) values('text'+"+i+","+i+",'"+(1320000+i)+""+"')");
}
database.setTransactionSuccessful();
database.endTransaction();
endTime = System.currentTimeMillis();
System.out.println("使用事务插入1w条数据耗时:"+(endTime-beginTime)+"毫秒");
5.获取listview显示的步骤
ListView 是一个在垂直滚动的列表中展示条目的控件。ListView上的条目内容来自于ListAdapter.
1.写布局
2.activity中找到listview
3.写一个类继承BaseAdapter,实现4个方法。
getcount:告诉listview要显示多少个条目
getItem:获取listview指定position条目上的数据对象。 该方法不影响listview的展示,可以先不实现。
getItemId:获取listview指定条目的id. 该方法不影响listview的展示,可以先不实现。
getView:告诉listview每个条目上显示的内容。 listview每显示一个条目getView方法就会被调用一次。 convertView:之前消失的那个item上的view对象
4.创建一个Adapter对象,设置给listview做条目的适配
listview.setAdapter(ListAdapter adapter)
6 常用获取inflate的写法
a.使用View.inflate
//需要创建一个复杂的布局转换成一个view对象。 context :上下文 ,resource :要填充的布局资源的id root:将要填充的布局用root包裹起来返回,一般传null
view = View.inflate(context, R.layout.item_news, null);//将一个布局文件填充成一个view对象
b.使用context.getSystemService
LayoutInflater layoutInfalter = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = layoutInfalter.inflate(R.layout.item_news, null);
c.使用LayoutInflate.from
LayoutInflater layoutInfalter = LayoutInflater.from(context);
view = layoutInfalter.inflate(R.layout.item_news, null);