Android系统内置一个Sqlite数据库,如果app需要使用Sqlite数据库数据库存储数据,Android会为此app生成一个.db文件。这个数据库在data/data/
如图,还是经典的用户系统,包括登录、注册、修改密码,同时还有删除用户,根据用户输入给出提示。这个系统在《【php】利用原生态的JavaScript Ajax为php进行MVC分层设计,兼容IE6》(点击打开链接)、《【Struts2+Hibernate3+Spring3】利用SSH整合,完成打印用户表,用户登录、注册、修改密码系统》(点击打开链接)、《【Servlet】根据MVC思想设计用户登陆、用户注册、修改密码系统》(点击打开链接)、《【mfc】利用文件的读写,theApp全局变量来现实登录帐号管理系统》(点击打开链接)等已经做了多次,不用再说了吧?主要是就是一个数据库的增删改查的过程。
一、数据库逻辑实现
首先整个安卓工程目录如下图,首先新建一个Sqlite工程,设置其主包为com.Sqlite.Activity,MainActivity最好在新建工程的时候就将其放在com.Sqlite.Activity里面,不然搞好工程再移比较麻烦,主要是区分com.Sqlite.dao用来放数据库执行方法的类,com.Sqlite.model用来放数据库实体的类,直接在src中新建这两个包。
Sqlite数据库的使用无需在AndroidManifest.xml申请任何权限。只要写好一个继承安卓固有接口SQLiteOpenHelper的类,之后这个类作为所有数据库的操作方法dao的构造方法继承这个类就OK了。
先在com.Sqlite.dao新建一个DBOpenHelper继承android.database.sqlite.SQLiteDatabase;
代码如下,具体见注释,其中onCreate中的SQL语句其实已经直接定义这个app在Sqlite数据库的表的结构。
package com.sqlite.dao;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
public class DBOpenHelper extends SQLiteOpenHelper {
public DBOpenHelper(Context context, String name, CursorFactory factory,
int version) {
super(context, "SqliteTest.db", null, 1);//向系统申请一个SqliteTest.db文件存这个数据库,其中1是数据库版本。
}
@Override
public void onCreate(SQLiteDatabase sqliteDatabase) {
String sql=
"create table if not exists t_user("+
"id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"+
"username VARCHAR(255),"+
"password VARCHAR(255),"+
"isDel INTEGER DEFAULT 0"+
")";//如果初次运行,建立一张t_user表,建表的时候注意,自增是AUTOINCREMENT,而不是mysql的AUTO_INCREMENT
sqliteDatabase.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
//这里是更新数据库版本时所触发的方法
}
}
之后,如同所有的MVC设计模式一样,如果你玩过Java的MVC设计模式,尤其是三大框架,就应该无比熟悉了。刚才建立了一张t_user表,里面有四个属性。其中这里搞标志删除,有一个isDel字段。那么我们就在com.Sqlite.model中搞一个User类,也就是对应t_user这张表的实体,代码如下,就一堆getter、setter方法。一个属性一个字段,用来传递数据用的。
package com.sqlite.model;
public class User {
private int id;
private String username;
private String password;
private int isDel;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getIsDel() {
return isDel;
}
public void setIsDel(int isDel) {
this.isDel = isDel;
}
}
最后,我们写t_user这张表的数据库的实现userDao.java,正如上面的所说构造方法需要初始化刚刚写的DBOpenHelper对象,代码如下,里面有各种数据库方法,写好,一会在写界面MainActivity.java等直接调用即可。
package com.sqlite.dao;
import java.util.ArrayList;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import com.sqlite.model.*;
public class UserDao {
private DBOpenHelper dbOpenHelper;// 创建DBOpenHelper对象
private SQLiteDatabase sqliteDatabase;// 创建SQLiteDatabase对象
public UserDao(Context context)// 定义构造函数
{
dbOpenHelper = new DBOpenHelper(context, null, null, 0);// 初始化DBOpenHelper对象
}
// 插入用户数据
public void dbInsert(String username, String password) {
sqliteDatabase = dbOpenHelper.getWritableDatabase();// 以读写方法打开数据库,不仅仅是写,getReadableDatabase()是只读
String sql = "insert into t_user(username,password,isDel) values (?,?,0)";
// 传递过来的username与password分别按顺序替换上面sql语句的两个?,自动转换类型,下同,不再赘述
Object bindArgs[] = new Object[] { username, password };
// 执行这条无返回值的sql语句
sqliteDatabase.execSQL(sql, bindArgs);
}
// 求出表中有多少条数据
public int dbGetUserSize() {
sqliteDatabase = dbOpenHelper.getWritableDatabase();
String sql = "select count(*) from t_user where isDel=0";
Cursor cursor = sqliteDatabase.rawQuery(sql, null);
if (cursor.moveToNext())// 判断Cursor中是否有数据
{
return cursor.getInt(0);// 返回总记录数
}
return 0;// 如果没有数据,则返回0
}
// 根据用户名查阅用户
public User dbQueryOneByUsername(String username) {
sqliteDatabase = dbOpenHelper.getWritableDatabase();
String sql = "select * from t_user where username=? and isDel=0";
String[] selectionArgs = new String[] { username };
Cursor cursor = sqliteDatabase.rawQuery(sql, selectionArgs);
if (cursor.moveToNext())// 判断Cursor中是否有数据
{
// 如果有用户,则把查到的值填充这个用户实体
User user = new User();
user.setId(cursor.getInt(cursor.getColumnIndex("id")));
user.setUsername(cursor.getString(cursor.getColumnIndex("username")));
user.setPassword(cursor.getString(cursor.getColumnIndex("password")));
return user;// 返回一个用户给前台
}
return null;// 没有返回null
}
// 根据用户名,修改密码
public void dbUpdatePassword(String username, String newPassword) {
sqliteDatabase = dbOpenHelper.getWritableDatabase();
String sql = "update t_user set password=? where username=? and isDel=0";
Object bindArgs[] = new Object[] { newPassword, username };
sqliteDatabase.execSQL(sql, bindArgs);
}
// 查询所有用户
public ArrayList dbQueryAll() {
ArrayList userArrayList = new ArrayList();
sqliteDatabase = dbOpenHelper.getWritableDatabase();
String sql = "select * from t_user where isDel=0";
Cursor cursor = sqliteDatabase.rawQuery(sql, null);
// 游标从头读到尾
for (cursor.moveToFirst(); !(cursor.isAfterLast()); cursor.moveToNext()) {
if (cursor.getInt(cursor.getColumnIndex("isDel")) != 1) {
User user = new User();
user.setId(cursor.getInt(cursor.getColumnIndex("id")));
user.setUsername(cursor.getString(cursor
.getColumnIndex("username")));
user.setPassword(cursor.getString(cursor
.getColumnIndex("password")));
userArrayList.add(user);
}
}
return userArrayList;
}
// 删除用户,其实是把相应的isDel值从0改1
public void dbDeleteUser(int id) {
sqliteDatabase = dbOpenHelper.getWritableDatabase();
String sql = "update t_user set isDel=1 where id=?";
Object bindArgs[] = new Object[] { id };
sqliteDatabase.execSQL(sql, bindArgs);
}
}
二、MainActivity.java,登录、注册、修改密码用户系统的实现
至此,数据库的逻辑实现结束了,下面开始界面的设置。
1、首先完成字符文件res\values\strings.xml修改如下,包括一会儿的TableActivity.java所用到的字体
Sqlite数据库的增删改查
Settings
用户登录:
用户注册:
修改密码:
用户名:
密码:
再次输入密码:
旧密码:
新密码:
确定
查看用户表
返回
2、之后完成MainActivity的布局,修改res\layout\activity_main.xml,采用到滚动的垂直自上而下的线性布局。这个布局同《【Android】内存卡图片读取器,图库app》( 点击打开链接),这里不再赘述。里面放置一个又一个的水平线性布局,这种布局方法很简单的,为要操作的控件赋予id。
3、之后MainActivity.java的实现如下,由于userDao有可能会传来null空值,注意怎么判空,不要出现空指针异常,具体可参考《【Java】对于空值null的判断》( 点击打开链接)。对于用户登录、注册、修改密码的逻辑判断不是这里讨论的重点,不过还是讲讲吧,登录就是看数据库有没有这个用户名,再看密码是否同;注册就是看数据库有没有这个用户名,没有则可以注册;修改密码,先看登录信息对不对,对则可以修改。最后留按钮打开用户表,打开的时候先关闭MainActivity,再打开TableActivity,主要是为了刷新一下MainActivity。
package com.sqlite.activity;
import com.sqlite.dao.*;
import com.sqlite.model.*;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import android.app.Activity;
import android.content.Intent;
public class MainActivity extends Activity {
// 用户登录
private EditText editTextA1;
private EditText editTextA2;
private Button buttonA1;
// 用户注册
private EditText editTextB1;
private EditText editTextB2;
private EditText editTextB3;
private Button buttonB1;
// 修改密码
private EditText editTextC1;
private EditText editTextC2;
private EditText editTextC3;
private EditText editTextC4;
private Button buttonC1;
//打开用户表
private Button button2;
// 数据库操作类
private UserDao userDao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 注册组件
userDao = new UserDao(this);
editTextA1 = (EditText) findViewById(R.id.editTextA1);
editTextA2 = (EditText) findViewById(R.id.editTextA2);
editTextB1 = (EditText) findViewById(R.id.editTextB1);
editTextB2 = (EditText) findViewById(R.id.editTextB2);
editTextB3 = (EditText) findViewById(R.id.editTextB3);
editTextC1 = (EditText) findViewById(R.id.editTextC1);
editTextC2 = (EditText) findViewById(R.id.editTextC2);
editTextC3 = (EditText) findViewById(R.id.editTextC3);
editTextC4 = (EditText) findViewById(R.id.editTextC4);
buttonA1 = (Button) findViewById(R.id.buttonA1);
buttonB1 = (Button) findViewById(R.id.buttonB1);
buttonC1 = (Button) findViewById(R.id.buttonC1);
button2 = (Button) findViewById(R.id.button2);
// 用户登录
buttonA1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
String username = editTextA1.getText() + "";
String password = editTextA2.getText() + "";
if (username.equals(null) || username == ""
|| password.equals(null) || password == "") {
Toast.makeText(MainActivity.this, "用户名或密码不得为空!",
Toast.LENGTH_SHORT).show();
} else {
User user = userDao.dbQueryOneByUsername(username);
if (userDao.dbQueryOneByUsername(username) == null) {
Toast.makeText(MainActivity.this, "此用户不存在!",
Toast.LENGTH_SHORT).show();
} else {
if (!user.getPassword().equals(password)) {
Toast.makeText(MainActivity.this, "密码错误!",
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "登录成功!",
Toast.LENGTH_SHORT).show();
}
}
}
}
});
// 用户注册
buttonB1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
String username = editTextB1.getText() + "";
String password = editTextB2.getText() + "";
if (username.equals(null) || username == ""
|| password.equals(null) || password == "") {
Toast.makeText(MainActivity.this, "用户名或密码不得为空!",
Toast.LENGTH_SHORT).show();
} else {
String confirmPwd = editTextB3.getText() + "";
if (!password.equals(confirmPwd)) {
Toast.makeText(MainActivity.this, "两次输入密码不一致!",
Toast.LENGTH_SHORT).show();
} else {
if (userDao.dbQueryOneByUsername(username) == null) {
userDao.dbInsert(username, password);
Toast.makeText(
MainActivity.this,
"注册成功!用户名:" + username + ",密码:" + password
+ ",请牢记!", Toast.LENGTH_SHORT)
.show();
} else {
Toast.makeText(MainActivity.this, "该用户已被注册",
Toast.LENGTH_SHORT).show();
}
}
}
}
});
// 修改密码
buttonC1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
String username = editTextC1.getText() + "";
String password = editTextC2.getText() + "";
if (username.equals(null) || username == ""
|| password.equals(null) || password == "") {
Toast.makeText(MainActivity.this, "用户名或密码不得为空!",
Toast.LENGTH_SHORT).show();
} else {
User user = userDao.dbQueryOneByUsername(username);
if (userDao.dbQueryOneByUsername(username) == null) {
Toast.makeText(MainActivity.this, "此用户不存在!",
Toast.LENGTH_SHORT).show();
} else {
if (!user.getPassword().equals(password)) {
Toast.makeText(MainActivity.this, "密码错误!",
Toast.LENGTH_SHORT).show();
} else {
String newPwd = editTextC3.getText() + "";
String confirmNewPwd = editTextC4.getText() + "";
if (!newPwd.equals(confirmNewPwd)) {
Toast.makeText(MainActivity.this, "两次输入密码不一致!",
Toast.LENGTH_SHORT).show();
} else {
userDao.dbUpdatePassword(username, newPwd);
Toast.makeText(MainActivity.this,
"修改密码成功!新密码:" + newPwd + ",请牢记!",
Toast.LENGTH_SHORT).show();
}
}
}
}
}
});
//打开用户表
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
finish();
Intent intent = new Intent(MainActivity.this, TableActivity.class);
startActivity(intent);
}
});
}
}
三、TableActivity.java,用户表的显示与删除用户
2、随后是TableActivity的布局,在res\layout中新建一个activity_table.xml,代码如下,里面还是采用一个滚动的垂直自上而下的线性布局。同时摆两个只设置好宽、高与tag的抽象View,一会儿利用《【Android】利用Java代码布局,按钮添加点击事件》( 点击打开链接)的方式,利用addChild带tag的方法在这些View中添加布局。
3、最后是TableActivity.java的实现,就是把用户表打印出来,再用Java代码一行一行带增加到表格布局TableLayout之中。这与.NET的表格控件有异曲同工之妙。注意按钮点击事件是如何获取按钮的id的,这在《【Android】画廊式的图片浏览器,使用HorizontalScrollView取代Gallery,OnClickListener的参数传递》( 点击打开链接)中已经说过了,这里不再赘述。
package com.sqlite.activity;
import java.util.ArrayList;
import com.sqlite.model.User;
import com.sqlite.dao.UserDao;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.Toast;
public class TableActivity extends Activity {
// 数据库操作类
private UserDao userDao;
//线性布局
private LinearLayout linearLayout1;
//返回按钮
private Button button3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_table);
// 注册组件
userDao = new UserDao(this);
button3 = (Button) findViewById(R.id.button3);
linearLayout1 = (LinearLayout) findViewById(R.id.linearLayout1);
//求出用户的数量,并且显示
int userSize = userDao.dbGetUserSize();
TextView textView1 = new TextView(this);
textView1.setText("共有" + userSize + "个用户");
textView1.setTextSize(24);
linearLayout1.addView(textView1, 1);//添加的textView1放到activity_table.xml中tag=1的View那个位置
//如果用户数量为0就不用搞这么东西添加表格布局了
if (userSize > 0) {
ArrayList userList = userDao.dbQueryAll();//查出表中的所有用户放到一个ArrayList中
TableLayout tableLayout1 = new TableLayout(this);//新建一个表格布局
tableLayout1.setStretchAllColumns(true);//自动宽度,使表格在横向占据100%
//打印表头
TableRow tableRow = new TableRow(this);//新建一行
TextView textView = new TextView(this);//新建一个TextView
textView.setTextSize(24);//设置字体
textView.setText("用户名");
tableRow.addView(textView);//放到行中,自动增加一个单元格
textView = new TextView(this);
textView.setTextSize(24);
textView.setText("密码");
tableRow.addView(textView);
textView = new TextView(this);
textView.setTextSize(24);
textView.setText("操作");
tableRow.addView(textView);
// 新建的行TableRow添加到表格TableLayout之中
tableLayout1.addView(tableRow, new TableLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.MATCH_PARENT));
//打印用户信息
for (int i = 0; i < userSize; i++) {
User user = userList.get(i);
// 一个用户占据一行
tableRow = new TableRow(this);
textView = new TextView(this);
textView.setTextSize(18);
textView.setText(user.getUsername());
tableRow.addView(textView);
textView = new TextView(this);
textView.setTextSize(18);
textView.setText(user.getPassword());
tableRow.addView(textView);
Button button = new Button(this);
button.setText("删除");
button.setTextSize(18);
button.setId(user.getId());//设置按钮的id就是用户的id
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
userDao.dbDeleteUser(view.getId());//这样可以获取按钮的id
//修改密码,更新数据库之后,刷新一下这个TableActivity
finish();
Intent intent = new Intent(TableActivity.this,
TableActivity.class);
startActivity(intent);
Toast.makeText(TableActivity.this, "删除成功!",
Toast.LENGTH_SHORT).show();
}
});
tableRow.addView(button);//将这个按钮添加到这行中
// 新建的TableRow添加到TableLayout
tableLayout1.addView(tableRow, new TableLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.MATCH_PARENT));
}
linearLayout1.addView(tableLayout1, 2);//把这个表格放到activity_table.xml中tag=2的View那个位置
}
//返回MainActivity
button3.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
finish();
Intent intent = new Intent(TableActivity.this, MainActivity.class);
startActivity(intent);
}
});
}
// 对物理按钮的监听
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
finish();// 关闭这个Activity。
Intent intent = new Intent(TableActivity.this, MainActivity.class);
startActivity(intent);
break;
}
return super.onKeyDown(keyCode, event);
}
}