Android移动应用开发之SQLite数据库
一、SQLite数据库简介
SQLite是遵循ACID的关系型数据库管理系统,即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
二、数据库的创建
使用SQLiteOpenHelper的子类创建数据库,重写onCreate和onUpgrade即可:
ublic class MyHelper extends SQLiteOpenHelper {
public MyHelper(Context context) {
super(context, "test.db", null, 2);
}
//数据库第一次被创建时使用该方法
@Override
public void onCreate(SQLiteDatabase db) {
//初始化数据库的表结构,执行一条建表的SQL语句
db.execSQL("CREATE TABLE information(_id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(20), price INTEGER)");
}
//当数据库的版本号增加时调用
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
三、数据库的使用
1、SQLite的基本操作
(1)增加一条数据
public void insert(String name, String price) {
SQLiteDatabase db = helper.getWritableDatabase(); //获取可读写SQLiteDatabase对象
ContentValues values = new ContentValues(); //创建ContentValues对象
values.put("name", name);
values.put("price", price);
long id = db.insert("information", null, values);
db.close();
}
(2)修改一条数据
public int update(String name, String price) {
SQLiteDatabase db = helper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("price", price);
int number = db.update("information", values, "name=?", new String[]{
name});
db.close();
return number;
}
(3)删除一条数据
public int delete(long id) {
SQLiteDatabase db = helper.getWritableDatabase();
int number = db.delete("information", "_id=?", new String[]{
id+""});
db.close();
return number;
}
(4)查询一条数据
public boolean find(long id) {
SQLiteDatabase db = helper.getReadableDatabase(); //获取可读SQLiteDatabase对象
Cursor cursor = db.query("information", null, "_id=?", new String[]{
id+""}, null, null,null);
boolean result = cursor.moveToNext();
cursor.close(); //关闭游标
db.close();
return result;
}
除此之外还可以用execSQL和rawQuery进行查询,但execSQL没有返回值而rawQuery有:
//增加一条数据
db.execSQL("insert into information (name, price) values (?, ?)", new Object[]{
name, price});
//修改一条数据
db.execSQL("update information set name=? where price=?", new Object[]{
name, price});
//删除一条数据
db.execSQL("delete from information where _id=1");
//执行查询的SQL语句
Cursor cursor = db.rawQuery("select * from person where name=?", new String[]{
name});
2、SQLite中的事务
PersonSQLiteOpenHelper helper = new PersonSQLiteOpenHelper(this);
SQLiteDatabase db = helper.getWritableDatabase();
//开始数据库事务
db.beginTransaction();
try {
//执行转出操作
db.execSQL("update person set account=account-1000 where name=?", new Object[]{
"zhangsan"});
//执行转入操作
db.execSQL("update person set account=account+1000 where name=?", new Object[]{
"lisi"});
//标记数据库事务执行成功
db.setTransactionSuccessful();
}catch (Exception e) {
Log.i("事务处理失败", e.toString());
}finally {
db.endTransaction(); //关闭事务
db.close(); //关闭数据库
}
3、实战演练:通讯录
布局文件activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/background"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
tools:context=".MainActivity">
<LinearLayout
android:id="@+id/ll_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="50dp"
android:layout_alignLeft="@+id/ll_btn"
android:layout_alignStart="@+id/ll_btn">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textStyle="bold"
android:text="姓 名:"/>
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textStyle="bold"
android:hint="请输入姓名" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_phone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_below="@+id/ll_name"
android:layout_alignLeft="@+id/ll_name"
android:layout_alignStart="@+id/ll_name">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textStyle="bold"
android:text="电 话:" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textStyle="bold"
android:hint="请输入手机号:" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/ll_phone"
android:layout_centerVertical="true">
<Button
android:id="@+id/btn_add"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="18sp"
android:background="#B9B9FF"
android:layout_marginRight="2dp"
android:text="添加" />
<Button
android:id="@+id/btn_query"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="18sp"
android:background="#DCB5FF"
android:layout_marginRight="2dp"
android:text="查询" />
<Button
android:id="@+id/btn_update"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="18sp"
android:background="#E6CAFF"
android:layout_marginRight="2dp"
android:text="修改" />
<Button
android:id="@+id/btn_delete"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="18sp"
android:background="#ACD6FF"
android:text="删除" />
</LinearLayout>
<TextView
android:id="@+id/tv_show"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/ll_btn"
android:layout_marginTop="253dp"
android:textSize="30sp" />
</RelativeLayout>
实现联系人信息的添加、查询、修改和删除MainActivity.java:
package edu.hzuapps.directory;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
MyHelper myHelper;
private EditText editName;
private EditText editPhone;
private TextView tvShow;
private Button btnAdd;
private Button btnQuery;
private Button btnUpdate;
private Button btnDelete;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myHelper = new MyHelper(this);
init(); //初始化控件
}
private void init() {
editName = (EditText)findViewById(R.id.et_name);
editPhone = (EditText)findViewById(R.id.et_phone);
tvShow = (TextView)findViewById(R.id.tv_show);
btnAdd = (Button)findViewById(R.id.btn_add);
btnDelete = (Button)findViewById(R.id.btn_delete);
btnQuery = (Button)findViewById(R.id.btn_query);
btnUpdate = (Button)findViewById(R.id.btn_update);
btnAdd.setOnClickListener(this);
btnUpdate.setOnClickListener(this);
btnQuery.setOnClickListener(this);
btnDelete.setOnClickListener(this);
}
@Override
public void onClick(View v) {
String name;
String phone;
SQLiteDatabase db;
ContentValues values;
switch (v.getId()) {
case R.id.btn_add: //添加数据
name = editName.getText().toString();
phone = editPhone.getText().toString();
db = myHelper.getWritableDatabase(); //获取可读写SQLiteDatabase对象
values = new ContentValues();
values.put("name", name);
values.put("phone",phone);
db.insert("information", null, values);
Toast.makeText(this,"信息已添加", Toast.LENGTH_SHORT).show();
db.close();
break;
case R.id.btn_query: //查询数据
db = myHelper.getReadableDatabase();
Cursor cursor = db.query("information", null, null, null, null, null, null);
if(cursor.getCount() == 0) {
tvShow.setText("");
Toast.makeText(this, "未找到该联系人", Toast.LENGTH_SHORT).show();
} else {
cursor.moveToFirst();
tvShow.setText("Name:"+cursor.getString(1)+" Tel:"+cursor.getString(2));
}
while (cursor.moveToNext()) {
tvShow.append("\n"+"Name:"+cursor.getString(1)+" Tel:"+cursor.getString(2));
}
cursor.close();
db.close();
break;
case R.id.btn_update: //修改数据
db = myHelper.getWritableDatabase();
values = new ContentValues(); //要修改的数据
values.put("phone", phone = editPhone.getText().toString());
db.update("information", values, "name=?", new String[]{
editName.getText().toString()}); //更新并得到行数
Toast.makeText(this, "联系人信息已修改", Toast.LENGTH_SHORT).show();
db.close();
break;
case R.id.btn_delete: //删除数据
db = myHelper.getWritableDatabase();
db.delete("information", "name=?", new String[]{
editName.getText().toString()});
Toast.makeText(this, "联系人信息已删除", Toast.LENGTH_SHORT).show();
tvShow.setText("");
db.close();
break;
}
}
}
class MyHelper extends SQLiteOpenHelper {
public MyHelper(Context context) {
super(context, "hzuapps.db",null,1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE information(_id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(20), phone VARCHAR(20))");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
四、数据展示监控
1、ListView控件
ListView用来展示具体数据内容,当数据过多时会出现滚动条,并且能够根据数据的长度自适应屏幕显示。
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent"></ListView>
</RelativeLayout>
2、常用数据适配器
(1)BaseAdapter:基本适配器
方法名称 | 功能描述 |
---|---|
public int getCount() | 得到Item条目的总数 |
public Object getItem(int position) | 根据position位置得到某个Item的对象 |
public long getItemId(int position) | 根据position位置得到摸个Item的ID |
public View getView(int position, View convertView, ViewGroup parent) | 得到相应position对应的Item视图,position是当前Item的位置,convertView用于复用旧视图,parent用于加载XML布局 |
(2)SimpleAdapter:继承自BaseAdapter
public SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to);
- Context context:语境,上下文对象。
- List<? extends Map
(3)ArrayAdapter:继承自BaseAdapter
ArrayAdapter通常用于适配TextView控件,例如设置菜单:
public ArrayAdapter(Context context, int resource);
public ArrayAdapter(Context context, int resource, int textViewResourceId);
public ArrayAdapter(Context context, int resource, T[] objects);
public ArrayAdapter(Context context, int resource, int textViewResourceId, T[] objects);
public ArrayAdapter(Context context, int resource, List<T> objects);
public ArrayAdapter(Context context, int resource, int textViewResourceId, List<T> objects);
- Context context:语境,上下文对象。
- int textViewResourceId:Item布局中相应的TextView的id。
- int resource:Item布局的资源id。
- T[] objects:需要适配的数据数组,数组类型数据。
- List<T> objects:需要适配的数据数组,List类型数据。
3、实战演练:Android应用市场
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:dividerHeight="1dp">
</ListView>
</RelativeLayout>
list_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical">
<ImageView
android:id="@+id/iv"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_margin="8dp"
android:background="@drawable/background" />
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ListView的Item布局"
android:textSize="18sp" />
</LinearLayout>
MainActivity.java:
package edu.hzuapps.applicationmarket;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private ListView listView;
//需要适配的数据
private String[] names = {
"京东商城", "QQ", "QQ斗地主", "新浪微博", "天猫", "UC浏览器", "微信"};
//图片集合
private int[] icons = {
R.drawable.jd, R.drawable.qq, R.drawable.qqddz, R.drawable.xl, R.drawable.tm, R.drawable.uc, R.drawable.wx};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化ListView控件
listView = (ListView) findViewById(R.id.lv);
//创建一个Adapter实例
MyBaseAdapter myBaseAdapter = new MyBaseAdapter();
//设置Adapter
listView.setAdapter(myBaseAdapter);
}
class MyBaseAdapter extends BaseAdapter {
//得到item的总数
@Override
public int getCount() {
//返回ListView Item条目的总数
return names.length;
}
//得到Item代表的对象
@Override
public Object getItem(int position) {
//返回ListView Item代表的对象
return names[position];
}
//得到Item的id
@Override
public long getItemId(int position) {
return position;
}
//得到Item的View视图
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//将list_item.xml文件找出来并转换成View对象
View view = View.inflate(MainActivity.this, R.layout.list_item, null);
TextView textView = (TextView) view.findViewById(R.id.tv);
textView.setText(names[position]);
ImageView imageView = (ImageView) view.findViewById(R.id.iv);
imageView.setBackgroundResource(icons[position]);
return view;
}
}
}
4、ListView的优化
如果展示的数据有成千上万条,那么需要创建成千上万个Item,会大大增加内存的消耗。ListView优化的两种方式:复用convertView,使用ViewHolder类。
(1)复用convertView
当滑动ListView时,顶部的Item会滑出屏幕,同时释放convertView,只要固定convertView即可避免每次创建Item而消耗的内存。
(2)使用ViewHolder类
在加载Item布局时,会使用findViewById方法找到Item中的各个控件,比较耗时,因此可以将要加载的子View放入ViewHolder中,第一次创建convertView时将这些控件找出,第二次直接通过getTag方法获取。在LayoutInflater.from方法需要传入一个Context对象作为参数,在Adapter中获取Context对象需要使用getApplicationContext方法。
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if(convertView == null) {
convertView = LayoutInflater.from(getApplicationContext()).inflate(R.layout.list_item, parent, false);
viewHolder = new ViewHolder();
viewHolder.textView.setText(names[position]);
viewHolder.imageView.setBackgroundResource(icons[position]);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.textView.setText(names[position]);
viewHolder.imageView.setBackgroundResource(icons[position]);
return convertView;
}
class ViewHolder {
TextView textView;
ImageView imageView;
}