对于更加复杂的数据结构, android提供了内置的SQLite数据库来存储数据.SQLite使用SQL命 令提供了完整的关系型数据库能力,每个使用SQLite的应用程序都有一个该数据库的实例,并且在默认情况下公限当前应用使用,数据库存存储在android设置 的/data/data//databases文件夹中.
这里创建数据库的操作对象要使用SQLiteOpenHelper类。
创建SqliteOpenHelper的继承类,需要传入数据库的名称。底层已经帮你创建好数据库。
使用SQLiteOpenHelper创建的helper对象
SQLiteDatabase db = helper.getReadableDatabase();
使用SQL语句,在自定义SQLiteOpenHelper类里面创建
db.execSQL(SQlite.CREATE_TABLE);
这里对数据库增删改查的操作都是使用db对象来进行的
增:
db.insert(String tableName,null,ContentValues values);第二个参数是占位符的使用。这里的values是键值对的形式put进去的
删:
db.delete(String tableName, ID + ” = ?”, new String[]{id + “”});
改:
db.update(String tebleName, ContentValues values, ID + “=?”, new String[]{user.id + “”});这里的values包含它要修改的信息。
adapter.notifyDataSetChanged();
查:
Cursor cursor =db.query(String tableName,….);
返回的是一个游标对象,使用moveToNext来获取数据
db.close();
下面用一个程序示例来说明Android数据库的使用:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">
<Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="insert" android:text="插入" />
<Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="select" android:text="查询" />
<ListView android:id="@+id/main_lv" android:layout_width="match_parent" android:layout_height="match_parent" />
</LinearLayout>
<?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:orientation="vertical">
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="10dp">
<TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="账号:" />
<EditText android:id="@+id/dialog_username" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="4" />
</LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="10dp">
<TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="年龄:" />
<EditText android:id="@+id/dialog_age" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="4" />
</LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="10dp">
<TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="性别:" />
<EditText android:id="@+id/dialog_sex" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="4" />
</LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="10dp">
<TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="信息:" />
<EditText android:id="@+id/dialog_info" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="4" />
</LinearLayout>
</LinearLayout>
<?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:orientation="horizontal">
<TextView android:id="@+id/id" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:padding="10dp" android:text="id" />
<TextView android:id="@+id/username" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:padding="10dp" android:text="username" />
<TextView android:id="@+id/age" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:padding="10dp" android:text="age" />
<TextView android:id="@+id/sex" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:padding="10dp" android:text="sex" />
<TextView android:id="@+id/info" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:padding="10dp" android:text="info" />
</LinearLayout>
package com.lwz.sqlite;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/** * Android轻量级数据库的使用 * 可以存放一些简单的数据,而且数据库的创建并不复杂,使用数据库对象直接创建表格就会产生数据库 * 它本质上其实就是文件储存,就是存放和读取的格式是数据库的形式 * 它保存的数据库文件在/data/data/<packagename>/databases 文件夹中 */
public class MySqliteOpenHelper extends SQLiteOpenHelper {
//构造方法
//第一个参数是上下文的意思
//第二个参数是数据库的名称
//第三个参数是游标工厂,一般使用null就可以
//第四个参数是版本号
public MySqliteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
//数据库没有创建才回调这个方法
//用于数据库的表的创建
@Override
public void onCreate(SQLiteDatabase db) {
//创建数据库的一个使用的表
db.execSQL(SQlite.CREATE_TABLE);
}
//版本变化时回调的方法,要求新版本大于旧版本呢!
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//删除数据库的表,再创建数据库的表
db.execSQL(SQlite.DELETE_TABLE);
onCreate(db);
}
//定义一个数据库的基本信息,包括一些基本的使用语句
static class SQlite {
public static final String DB_NAME = "Test.db";//数据库名称
public static final String TABLE_NAME = "userInfo";//要操作的表的名称
//表格里面的数据
public static final String ID = "_id";//用户的ID
public static final String USER_USERNAME = "username";//用户的姓名
public static final String USER_AGE = "age";//用户的年龄
public static final String USER_SEX = "sex";//用户的性别
public static final String USER_INFO = "info";//用户的其他信息
//创建表格使用的SQL语句
public static final String CREATE_TABLE = "create table " + TABLE_NAME + " (" + ID + " integer primary key autoincrement," + USER_USERNAME + " text not null," + USER_AGE + " integer," + USER_SEX + " varchar(1)," + USER_INFO + " text" + ")";
//删除表格使用的语句
public static final String DELETE_TABLE = "drop table if exists " + TABLE_NAME;
}
}
package com.lwz.sqlite;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
/** * Android数据库的使用 * 使用ListView显示数据 */
public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener {
//定义ListView布局
ListView listView;
//存放数据的集合
List<User> list = new ArrayList<>();
//定义一个数据库的对象
SQLiteDatabase db;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.main_lv);
//实例化数据库对象
//要通过SQLiteHelper对象,这里使用的是自己定义的类
MySqliteOpenHelper helper = new MySqliteOpenHelper(this, MySqliteOpenHelper.SQlite.DB_NAME, null, 1);
//获得数据库对象helper.get...
//可读,并且可写---的数据库: 磁盘满的情况,写不进去,不写了,一般情况使用这个
db = helper.getReadableDatabase();
/* //可读,并且可写---的数据库:磁盘满的情况,写不进去。报错,崩溃了 db = helper.getReadableDatabase();*/
//给ListView设置适配器
listView.setAdapter(adapter);
//给ListView设置监听事件
listView.setOnItemClickListener(this);
listView.setOnItemLongClickListener(this);
}
/** * 插入数据的方法 */
public void insert(View v) {
//1 插入
//ContentValues是以一种键值对的形式存储数据的
ContentValues values = new ContentValues();
values.put(MySqliteOpenHelper.SQlite.USER_USERNAME, "张三");
values.put(MySqliteOpenHelper.SQlite.USER_AGE, 58);
values.put(MySqliteOpenHelper.SQlite.USER_SEX, "男");
values.put(MySqliteOpenHelper.SQlite.USER_INFO, "IT工程师---张工");
db.insert(MySqliteOpenHelper.SQlite.TABLE_NAME, null, values);
//插入后进行一次查询
select();
}
/** * 查询数据 */
public void select(View v) {
select();
}
/** * 查询数据库的具体实现 */
private void select() {
//先清除页面上的数据
list.clear();
//再加载数据库的数据
//这里查询所有的数据,只需要一个表名就可以了,后面的条件可以不写,获得的是一个结果集
Cursor cursor = db.query(MySqliteOpenHelper.SQlite.TABLE_NAME, null, null, null, null, null, null);
//结果集指向的表头前面.moveToNext()来指向下一个结果
while (cursor.moveToNext()) {
//获取结果集里面的数据
//cursor.getColumnIndex()获取列名所在的列号
User user = new User();
//这里通过列号来获取数据
user.id = cursor.getInt(cursor.getColumnIndex(MySqliteOpenHelper.SQlite.ID));
user.age = cursor.getInt(cursor.getColumnIndex(MySqliteOpenHelper.SQlite.USER_AGE));
user.username = cursor.getString(cursor.getColumnIndex(MySqliteOpenHelper.SQlite.USER_USERNAME));
user.info = cursor.getString(cursor.getColumnIndex(MySqliteOpenHelper.SQlite.USER_INFO));
user.sex = cursor.getString(cursor.getColumnIndex(MySqliteOpenHelper.SQlite.USER_SEX));
//把找到的数据添加到List集合中
list.add(user);
}
//刷新适配器
adapter.notifyDataSetChanged();
}
/** * 适配器的创建,为了显示ListView */
BaseAdapter adapter = new BaseAdapter() {
@Override
public int getCount() {
return list.size();
}
@Override
public User getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//定义ViewHolder对象
ViewHolder holder;
if (convertView == null) {
convertView = View.inflate(MainActivity.this, R.layout.item_listview, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
//往控件上放置数据
User user = list.get(position);
holder.age.setText(user.age + ""); //如果不是String类型的数据会报错ResourceNotFound
holder.info.setText(user.info + "");
holder.username.setText(user.username + "");
holder.sex.setText(user.sex + "");
holder.id.setText(user.id + "");
//返回视图
return convertView;
}
//创建一个ViewHolder
class ViewHolder {
//定义控件对象
TextView id, info, sex, username, age;
//通过构造方法传入控件存在的View的对象
ViewHolder(View convertView) {
//实例化控件对象
id = (TextView) convertView.findViewById(R.id.id);
info = (TextView) convertView.findViewById(R.id.info);
sex = (TextView) convertView.findViewById(R.id.sex);
username = (TextView) convertView.findViewById(R.id.username);
age = (TextView) convertView.findViewById(R.id.age);
}
}
};
//点击ListView里面的条目时触发的方法,这里修改数据
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//要修改的属性的用户对象
final User user = list.get(position);
// 创建一个布局的VIew对象
View dialogView = View.inflate(this, R.layout.dailog_layout, null);
//定义布局内的控件
final EditText et_name = (EditText) dialogView.findViewById(R.id.dialog_username);
final EditText et_age = (EditText) dialogView.findViewById(R.id.dialog_age);
final EditText et_sex = (EditText) dialogView.findViewById(R.id.dialog_sex);
final EditText et_info = (EditText) dialogView.findViewById(R.id.dialog_info);
//给布局内添加选择的条目的信息
et_name.setText(user.username + "");
et_age.setText(user.age + "");
et_sex.setText(user.sex + "");
et_info.setText(user.info + "");
// 创建对话框对象
new AlertDialog.Builder(this).
// 设置标题
setTitle("请输入要修改信息").
// 添加输入的文本框
setView(dialogView).
// 添加确定按钮
setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//或用户输入的信息并保存到数据库中
//修改使用的是ContentValues键值对put的方法
ContentValues values = new ContentValues();
user.username = et_name.getText().toString();
try {
user.age = Integer.parseInt(et_age.getText().toString());
} catch (Exception e) {
Toast.makeText(MainActivity.this, "你输入的年龄格式不正确!", Toast.LENGTH_SHORT).show();
}
//数据的修改
user.sex = et_sex.getText().toString();
user.info = et_info.getText().toString();
values.put(MySqliteOpenHelper.SQlite.USER_USERNAME, user.username);
values.put(MySqliteOpenHelper.SQlite.USER_AGE, user.age);
values.put(MySqliteOpenHelper.SQlite.USER_SEX, user.sex);
db.update(MySqliteOpenHelper.SQlite.TABLE_NAME, values, MySqliteOpenHelper.SQlite.ID + "=?", new String[]{user.id + ""});
adapter.notifyDataSetChanged();
}
}).
// 添加取消按钮
setNegativeButton("取消", null).
// 产生并显示
create().show();
}
//长按ListView里面的条目时触发的方法,这里删除数据
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {
//弹出一个对话框,询问是否删除数据
new AlertDialog.Builder(this).
setTitle("警告").
setMessage("是否确定删除信息!").
setNegativeButton("取消", null)
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//点击确定后,删除信息
//获取点中的条目的用户的ID值
int id = list.get(position).id;
int rows = db.delete(MySqliteOpenHelper.SQlite.TABLE_NAME, MySqliteOpenHelper.SQlite.ID + " = ?", new String[]{id + ""});
//在集合中也删除这条数据
if (rows > 0) {
list.remove(position);
}
//刷新适配器
adapter.notifyDataSetChanged();
}
}).show();
return true;
}
//定义一个内部类方便数据的集体存放
class User {
int id;
String username;
String info;
int age;
String sex;
}
//页面关闭时,关闭数据库的连接
@Override
protected void onDestroy() {
super.onDestroy();
db.close();
}
}
长按条目事件的结果:
上面程序间接实现了SQLite数据库的增删改查操作。
增:点击按钮执行
删:长按后,选择确定时执行
改:点击ListView里面某个数据时执行
查:各种操作后,或点击查询按钮时执行
其中SQLite数据库的数据是保存在本地文件中的,所以关闭数据库后,下次打开还是可以查询到之前操作的数据的。