这是【Android学习之路】之从零开始做一个小项目的第二篇,欢迎阅读~
📋本文目录
目前进度
① 在第一篇汇报的进度下进行了登录注册页面和功能的大换血!
② 手机短信验证已经莫得问题,适应十分良好
③ 在操纵数据库方面有了很大改善
④ 解决了上一期中读取数据库数据不正确的问题
对于这次的拖更我很抱歉🙏,因为前几天一直在冲刺计算机大赛的最后阶段,所以这篇博客写了前前后后四五天都迟迟没有更新,周一的时候遇到的深坑困住了我,我想了想得先把它解决了再写博客总结叭,然后就与之战斗到了周二(相应的深坑在下面的内容中会讲到)
聊一聊这次改进的地方
登录注册页面大换血
在第一期的博客中,我的登录和注册都在同一个一面(而且当时有一个数据库读取数据相关的bug,所以我加上了需要点击两次注册的说明,其实是为了先避开这个bug😅):
这周我已经解决了这个bug,或者说我换了一种方式来进行数据库数据的读取和比较等操作,当然这个一会儿会做讲解,现在先聊一聊我在登陆和注册页面的改进~
① 教师用户:
当你从初始页面中选择了【我是教师】之后跳转至教师页面(这里的登录界面并没有大的改变,主要是修改了【注册】按钮的功能,让其跳转至教师注册页面)
还有就是对账号的注册和输入格式进行了一定的限制
(因为登录按钮点击后的对输入内容的检查功能除了刚刚提到的账号格式限制外,和第一期的并没有什么大变化,所以这里就以注册界面及功能为主进行讲解)
点击【注册】按钮后:销毁当前Activity并跳转至教师注册页面,我采用了手机短信验证的方式对教师用户的注册设置一定的限制(提前录入允许注册的手机号,而且在知道可用于注册的手机号后还需获得它的验证码,如果不是自己的手机一般不会知道其短信验证码是多少,所以一定程度上增强了安全性),同时我对输入的手机号采用正则表达式进行了校验,不允许输入不正确的手机号,如下所示:
public static boolean checkTel(String tel){
Pattern p = Pattern.compile("^[1][3,4,5,7,8,9][0-9]{9}$");
Matcher matcher = p.matcher(tel);
return matcher.matches();
}
手机格式正确的情况下会进一步验证数据库中该手机号是否已经和用户绑定(具体代码一会在数据库改进讲解之后贴出来),这里先进行演示:
可看到上图中,我先是输入了一个我之前注册用过的手机号,点击【获取验证码】按钮后,查询到数据库中已有与该手机号绑定的用户,所以弹出弹窗提示用户,同时将输入框清空。然后我用另一个手机号进行注册,成功获取验证码(这里接受验证码时的短信提示窗口被我顺手给划掉了,,没事一会下面还有截图能看得到😂)
— — — — — — — — — — — — — — — — —
获取到验证码后填入账号和密码,这里同样也对输入框中的内容进行了检验,账号为英文和数字的组合,不超过10个字符,同时账号和密码输入框均不能为空,为空则注册失败且弹出弹窗提示。
需要注意的是:当注册失败(即不满足格式要求)被弹窗提示后当前验证码失效,需要重新获取,下图对该过程进行演示:
重新获取验证码并填写后,点击【注册】,因为Henry
这个账号之前已经被我注册过了,数据库中已经有其信息,所以当然也是注册失败啦,弹窗提示的同时清空除了手机号以外的其他输入框,如下图所示:
好了,终于把目前各种可能出现的情况都演示完了,下面就好好地注册一个账号叭👦~
我这里账号就取名为HQ(忘记截图了,,不过一会登录成功可以看到),成功注册后注销当前页面同时跳转至教师登录页面,弹窗提示注册成功,如下图:
我这里就不演示登录过程了哈,一些检验啥的和第一期里的基本一致,直接放上登陆成功的截图:
— — — — — — — — — — — — — — — — — — — — — — — — — — — —
② 学生用户:
如果从初始页面中选择的是【我是学生】之后跳转至学生登录页面:
点击【注册】按钮后:销毁当前Activity并跳转至学生注册页面,我采用了学生学号验证的方式对学生用户的注册设置一定的限制(提前录入允许注册的学号,这里的安全性暂时不如教师注册的安全性强,以后会加上【忘记密码】功能,同样采取手机号绑定的方式增强其安全性),我提前录入的学号有下面的十个(下一步打算将其存储于数据库中,当数据库初始化的时候自动插入在数据库内):
public class IDUtils {
public static String[] studentID= {
"202001","202002","202003","202004","202005","202006","202007","202008","202009","202010"};
}
这里对学号的检测演示如下图所示:
同样的,学生端注册也具有对输入的账号和密码的检验,账号为英文和数字的组合,不超过10个字符,同时账号和密码输入框均不能为空,为空则注册失败且弹出弹窗提示,因为和教师端的大同小异,这里就不做演示啦,当注册成功后进行登录,同样的登陆成功后跳转至学生端的个人页面,同时弹窗提示:
读取SQLite数据库中的数据后与输入数据优雅地比较
上一期,也就是第一阶段中,我采用的是在需要用到数据库的类中实例化DBOpenHelper(我定义的数据库帮助类),读取数据时采用的是cursor读取后存入HashMap中,然后将其存入一个ArrayList中,再利用对这个ArrayList来进行和输入框中数据的比较。
这样的方式下有一个bug就是我总是读取不到第一条数据(当然这是我目前水平的原因,,以后能力提升之后会好好研究一下为啥读不到第一条数据),所以需要注册两次,这样数据库中一条信息就被存储了两遍,没有必要而且在注册时判断用户是否已存在也不方便,终于在我查阅了很多写法之后用了以下的方式很好地解决了这个问题:
① 首先改变了DBOpenHelper的写法:
// public DBOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
// super(context, name, null, version); //重写构造方法并设置factory为null
// }
public DBOpenHelper(Context context){
super(context, "mySchool.db", null, 1);
}
运用了Context,Android程序员把“场景”抽象为Context类,他们认为用户和操作系统的每一次交互都是一个场景,在应用程序中Context的具体实现子类就是:Activity,Service,Application。
② 我新建了一个bean包,目前里面有TeacherBean和StudentBean两个类,把要在操作数据库时会重复多次运用到的东西放在了里面,如下:
package com.henry.myschoolsystem.bean;
public class StudentBean {
public String userName; //账号
public String nickName; //昵称
public String sex; //性别
public String qq; //QQ号
public String wechat; //微信号
public String motto; //个性签名
public String ID; //学生学号
public String password; //密码
}
package com.henry.myschoolsystem.bean;
public class TeacherBean {
public String userName; //账号
public String nickName; //昵称
public String sex; //性别
public String qq; //QQ号
public String wechat; //微信号
public String motto; //个性签名
public String phoneNumber; //教师手机号
public String password; //密码
}
③ 同时新建了DBUtils类来写对数据库的相关操作方法,现在我的utils包中已有四个自定义的工具类:
DBUtils类完整代码如下:
package com.henry.myschoolsystem.utils;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import com.henry.myschoolsystem.bean.StudentBean;
import com.henry.myschoolsystem.bean.TeacherBean;
import com.henry.myschoolsystem.ui.login.DBOpenHelper;
public class DBUtils {
private static DBUtils instance = null;
private static DBOpenHelper dbHelper;
private static SQLiteDatabase db;
/**
* 构造方法,只有当类被实例化时候调用
* 实例化DBOpenHelper类,从中得到一个可读写的数据库
**/
public DBUtils(Context context) {
dbHelper = new DBOpenHelper(context);
db = dbHelper.getWritableDatabase();
}
/**
* 得到这个类的实例
**/
public static DBUtils getInstance(Context context) {
if (instance == null) {
instance = new DBUtils(context);
}
return instance;
}
/**
* 保存教师资料信息
**/
public void saveTeacherInfo(TeacherBean teacherBean) {
ContentValues cv = new ContentValues();
cv.put("userName", teacherBean.userName);
cv.put("nickName", teacherBean.nickName);
cv.put("sex", teacherBean.sex);
cv.put("qq", teacherBean.qq);
cv.put("wechat",teacherBean.wechat);
cv.put("motto",teacherBean.motto);
cv.put("phoneNumber",teacherBean.phoneNumber);
cv.put("password",teacherBean.password);
db.insert(DBOpenHelper.TEACHER_INFO, null, cv);
}
/**
* 保存学生资料信息
**/
public void saveStudentInfo(StudentBean studentBean) {
ContentValues cv = new ContentValues();
cv.put("userName", studentBean.userName);
cv.put("nickName", studentBean.nickName);
cv.put("sex", studentBean.sex);
cv.put("qq", studentBean.qq);
cv.put("wechat",studentBean.wechat);
cv.put("motto",studentBean.motto);
cv.put("ID",studentBean.ID);
cv.put("password",studentBean.password);
db.insert(DBOpenHelper.STUDENT_INFO, null, cv);
}
// ---------------------------------------------------------------------------------------------
/**
* 通过账号获取教师资料信息
**/
public TeacherBean getTeacherInfo(String teacherName) {
String sql = "SELECT * FROM " + DBOpenHelper.TEACHER_INFO + " WHERE userName=?";
Cursor cursor = db.rawQuery(sql, new String[]{
teacherName});
TeacherBean teacherBean = null;
while (cursor.moveToNext()) {
teacherBean = new TeacherBean();
//将对应用户名的所有数据从表中动态赋值给bean
teacherBean.userName = cursor.getString(cursor.getColumnIndex("userName"));
teacherBean.nickName = cursor.getString(cursor.getColumnIndex("nickName"));
teacherBean.sex = cursor.getString(cursor.getColumnIndex("sex"));
teacherBean.qq = cursor.getString(cursor.getColumnIndex("qq"));
teacherBean.wechat = cursor.getString(cursor.getColumnIndex("wechat"));
teacherBean.motto = cursor.getString(cursor.getColumnIndex("motto"));
teacherBean.phoneNumber = cursor.getString(cursor.getColumnIndex("phoneNumber"));
teacherBean.password = cursor.getString(cursor.getColumnIndex("password"));
}
cursor.close();
return teacherBean;
}