用户登录以及注册功能的普遍使用就不用我说了,任何一款应用软件基本都具有登录和注册功能,今天通过前面的学习,我写了一个小demo,就是使用MVP模式写一个用户登录和注册的功能。有关MVP模式我就不做讲解了,通常来说很多实现的登录或者注册功能都是使用MVC的模式来实现的,今天我将采用MVP模式来实现这个小demo,主要是为了巩固数据库部分的知识点,然后让大家熟悉MVP这种模式,看看MVP模式的优势在哪里(其实MVP最主要的就是达到完全解耦,不同的层实现不同的功能,互不影响)。
案例的主要功能:
1. 用户登录
2. 用户注册
模拟场景:当用户点击登录按钮时,模式了一个延时3秒的操作,相当于从服务器获取用户登录信息,3秒后返回登录结果。注册也是一样
老样子,主要功能在程序中注释
ViewInter.java
/**
* view层所有的功能
*/
public interface ViewInter {
//获取用户名
String getName();
//获取用户密码
String getPass();
//清除界面中编辑框里的名字
void clearUserName();
//清除界面中编辑框里的密码
void clearUserPass();
//显示进度条
void showLoading();
//隐藏进度条
void hideLoading();
/**
* 提示用户登录或注册成功后的状态
* @param user 用户信息
* @param tag 表示登录或注册提示
*/
void successHint(User user, String tag);
/**
* 提示用户登录或注册失败后的状态
* @param user 用户信息
* @param tag 表示登录或注册提示
*/
void failHint(User user, String tag);
}
Login.java
public class Login extends AppCompatActivity implements ViewInter{
private EditText mUserName;//用户名控件
private EditText mUserPwd;//用户密码控件
private Button mBtnLogin;//登录按钮
private Button mBtnClear;//清除按钮
private ProgressBar mProBar;//进度条
private TextView mRegister;//点我注册控件
private Presenter presenter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
//初始化控件
initView();
//初始化事件
event();
//建立与presenter层的关系,创建presenter对象
presenter = new Presenter(this, Login.this);
}
private void initView() {
mUserName = (EditText) findViewById(R.id.user_name);
mUserPwd = (EditText) findViewById(R.id.user_pwd);
mBtnLogin = (Button) findViewById(R.id.btn_login);
mBtnClear = (Button) findViewById(R.id.btn_clear);
mProBar = (ProgressBar) findViewById(R.id.progressBar);
mRegister = (TextView) findViewById(R.id.mRegister);
}
private void event() {
/**
* 登录响应事件
*/
mBtnLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//告诉presenter层,我需要登录操作
presenter.login();
}
});
/**
* 清除响应事件
*/
mBtnClear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//告诉presenter层,我需要清除操作
presenter.clear();
}
});
/**
* 点击注册响应事件,跳转到注册界面
*/
mRegister.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(Login.this,Register.class);
startActivity(intent);
finish();
}
});
}
@Override
public String getName() {
return mUserName.getText().toString();
}
@Override
public String getPass() {
return mUserPwd.getText().toString();
}
@Override
public void clearUserName() {
mUserName.setText("");
}
@Override
public void clearUserPass() {
mUserPwd.setText("");
}
@Override
public void showLoading() {
mProBar.setVisibility(View.VISIBLE);
}
@Override
public void hideLoading() {
mProBar.setVisibility(View.GONE);
}
@Override
public void successHint(User user,String tag) {
Toast.makeText(this,"用户" + user.getUserName() + tag + "成功",Toast.LENGTH_SHORT).show();
}
@Override
public void failHint(User user,String tag) {
Toast.makeText(this,"用户" + user.getUserName() + tag + "失败,密码或账号不正确,maybe not this user",Toast.LENGTH_LONG).show();
}
}
Register.java
public class Register extends AppCompatActivity implements ViewInter {
private EditText mUserName;
private EditText mUserPwd;
private Button mBtnRegister;
private Button mBtnClear;
private ProgressBar mProBar;
private TextView mTvLogin;//点击注册控件
private Presenter presenter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
initView();
event();
presenter = new Presenter(this, Register.this);
}
private void initView() {
mUserName = (EditText) findViewById(R.id.user_name);
mUserPwd = (EditText) findViewById(R.id.user_pwd);
mBtnRegister = (Button) findViewById(R.id.btn_register);
mBtnClear = (Button) findViewById(R.id.btn_clear);
mProBar = (ProgressBar) findViewById(R.id.progressBar);
mTvLogin = (TextView) findViewById(R.id.mTvLogin);
}
private void event() {
/**
* 注册功能
*/
mBtnRegister.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
presenter.register();
}
});
/**
* 清除功能
*/
mBtnClear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
presenter.clear();
}
});
/**
* 启动登录界面
*/
mTvLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(Register.this,Login.class);
startActivity(intent);
finish();
}
});
}
@Override
public String getName() {
return mUserName.getText().toString();
}
@Override
public String getPass() {
return mUserPwd.getText().toString();
}
@Override
public void clearUserName() {
mUserName.setText("");
}
@Override
public void clearUserPass() {
mUserPwd.setText("");
}
@Override
public void showLoading() {
mProBar.setVisibility(View.VISIBLE);
}
@Override
public void hideLoading() {
mProBar.setVisibility(View.GONE);
}
@Override
public void successHint(User user, String tag) {
Toast.makeText(this, "用户" + user.getUserName() + tag + "成功", Toast.LENGTH_SHORT).show();
}
@Override
public void failHint(User user, String tag) {
Toast.makeText(this, "用户" + user.getUserName() + tag + "失败,已存在该用户", Toast.LENGTH_SHORT).show();
}
}
Presenter.java
public class Presenter {
//view层的控件,对view层进行操作
ViewInter viewInter;
//模型层的控件,对model层进行操作
ModelInter modelInter;
public Presenter(ViewInter viewInter, Context context) {
this.viewInter = viewInter;
modelInter = new ModelImp(context);
}
/**
* 注册功能
*/
public void register() {
//显示进度条
viewInter.showLoading();
//控制层开始处理数据,拿到视图层的name,pass之后,进行注册操作
//OnRegisterListener匿名内部类
modelInter.register(viewInter.getName(), viewInter.getPass(), new OnRegisterListener() {
/**
* 如果注册成功模型层就会调用该方法
* 其中的handler表示模拟延时3秒响应操作
* @param user 返回已经注册的用户信息
*/
@Override
public void registerSuccess(final User user) {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
//隐藏进度条
viewInter.hideLoading();
//返回成功状态信息
viewInter.successHint(user,TAG);
}
}, 3000);
}
/**
* 如果注册失败模型层就会调用该方法
* 其中的handler表示模拟延时3秒响应操作
* @param user 返回未注册的用户信息
*/
@Override
public void registerFail(final User user) {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
//隐藏进度条
viewInter.hideLoading();
//返回失败状态信息
viewInter.failHint(user,TAG);
}
}, 3000);
}
});
}
/**
* 清除功能
*/
public void clear() {
viewInter.clearUserName();
viewInter.clearUserPass();
}
/**
* 登录功能,其基本实现和注册一样,只是模型层处理的逻辑不一样
*/
public void login(){
viewInter.showLoading();
modelInter.login(viewInter.getName(), viewInter.getPass(), new OnLoginListener() {
@Override
public void loginSuccess(final User user) {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
viewInter.hideLoading();
viewInter.successHint(user,TAG);
}
},3000);
}
@Override
public void loginFail(final User user) {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
viewInter.hideLoading();
viewInter.failHint(user,TAG);
}
},3000);
}
});
}
}
ModelInter.java
/**
* 所有数据处理操作功能都定义在这个接口中,方便扩展
*/
public interface ModelInter {
/**
* 注册操作
*
* @param name 用户名
* @param pass 用户密码
* @param listener 回调事件,如果成功调用注册成功方法,失败调用注册失败方法
*/
void register(String name, String pass, OnRegisterListener listener);
/**
* 登录操作
*
* @param name 用户名
* @param pass 用户密码
* @param listener 回调事件,如果成功调用登录成功方法,失败调用登录失败方法
*/
void login(String name, String pass, OnLoginListener listener);
}
OnLoginListener.java
/**
* 登录成功或失败的接口
*/
public interface OnLoginListener {
//表示登录标签
String TAG = "登录";
/**
* 登录成功,传递了用户信息
*
* @param user
*/
void loginSuccess(User user);
/**
* 登录失败,传递了用户信息
*
* @param user
*/
void loginFail(User user);
}
OnRegisterListener.java
/**
* 注册成功或失败的接口
*/
public interface OnRegisterListener {
//表示注册标签
String TAG = "注册";
/**
* 注册成功,传递了用户信息
*
* @param user
*/
void registerSuccess(User user);
/**
* 注册失败,传递了用户信息
*
* @param user
*/
void registerFail(User user);
}
ModelIpm.java
/**
* 整体的逻辑实现,判断是否登录成功,失败
*/
public class ModelImp implements ModelInter {
//获取数据库管理类,对数据库进行操作
private UserDao userDao;
public ModelImp(Context context){
userDao = new ImpUserDao(context);
}
/**
* 注册逻辑实现
* @param name 用户名
* @param pass 用户密码
* @param listener 回调事件,如果成功调用注册成功方法,失败调用注册失败方法
*/
@Override
public void register(String name, String pass, OnRegisterListener listener) {
//将用户名和密码封装到user中
User user = new User(name,pass);
//数据库不存在该用户注册成功,否则注册失败
if(userDao.isExistsUser(user)){
listener.registerFail(user);
}else{
userDao.addUser(user);
listener.registerSuccess(user);
}
}
/**
* 登录逻辑实现
* @param name 用户名
* @param pass 用户密码
* @param listener 回调事件,如果成功调用登录成功方法,失败调用登录失败方法
*/
@Override
public void login(String name, String pass, OnLoginListener listener) {
User user = new User(name,pass);
//判断是否登录成功
if(userDao.isLoginSuccess(user)){
listener.loginSuccess(user);
}else{
listener.loginFail(user);
}
}
}
UserDao.java
public interface UserDao {
void addUser(User user);//添加新用户
void delteUserByName(String name);//删除用户
void updateUserPwd(String name, String pass);//通过同户名修改密码
User queryUserByName(String name);//通过用户名查找用户
boolean isExistsUser(User user);//判断是否存在重复用户
boolean isLoginSuccess(User user);
}
ImpUserDao.java
/**
* 在这个方法中,我都采用了两种对数据进行操作的方法,一种是sql语句,一种是直接调用封装好了的方法
* 哪种方式都可以,看个人爱好
*/
public class ImpUserDao implements UserDao {
private DBHelper dbHelper;
private SQLiteDatabase database;
private ContentValues values;
public ImpUserDao(Context context) {
dbHelper = new DBHelper(context);
}
/**
* 添加新用户
* @param user 注册的用户信息
*/
@Override
public void addUser(User user) {
database = dbHelper.getWritableDatabase();
//方式一:sql语句操作数据库
// String sql = "insert into users(uName,uPass) values(?,?)";
// database.execSQL(sql,new Object[]{user.getUserName(),user.getUserPass()});
//方法二:封装的api操作,直接操作方法即可
values = new ContentValues();
values.put(DBHelper.COLNUMNAME, user.getUserName());
values.put(DBHelper.COLNUMPASS, user.getUserPass());
database.insert(DBHelper.TABLENAME, null, values);
database.close();
}
/**
* 根据名字删除用户
*
* @param name 要删除用户的名字
*/
@Override
public void delteUserByName(String name) {
database = dbHelper.getWritableDatabase();
//方式一:sql语句操作数据库
// String sql = "delete from " + DBHelper.TABLENAME + " where " + DBHelper.COLNUMNAME + " = ?";
// database.execSQL(sql,new Object[]{name});
//方法二:封装的api操作,直接操作方法即可
database.delete(DBHelper.TABLENAME,DBHelper.COLNUMNAME + " = ?",new String[]{name});
database.close();
}
/**
* 更新用户密码
*
* @param name 用户名
* @param pass 用户密码
*/
@Override
public void updateUserPwd(String name, String pass) {
database = dbHelper.getWritableDatabase();
//方式一:sql语句操作数据库
// String sql = "update " + DBHelper.TABLENAME + " set " + DBHelper.COLNUMPASS + " = ? where " + DBHelper.COLNUMNAME + " = ?";
// database.execSQL(sql,new Object[]{pass,name});
//方法二:封装的api操作,直接操作方法即可
values = new ContentValues();
values.put(DBHelper.COLNUMPASS,pass);
database.update(DBHelper.TABLENAME,values,DBHelper.COLNUMNAME + " = ?",new String[]{pass});
database.close();
}
/**
* 通过用户名查找用户
*
* @param name
*/
@Override
public User queryUserByName(String name) {
database = dbHelper.getReadableDatabase();
//方式一:sql语句操作数据库
// String sql = "select * from " + DBHelper.TABLENAME + " where " + DBHelper.COLNUMNAME + " = ?";
// Cursor cursor = database.rawQuery(sql, new String[]{name});
//方法二:封装的api操作,直接操作方法即可
Cursor cursor = database.query(DBHelper.TABLENAME, null, DBHelper.COLNUMNAME + " = ?", null, null, null, null);
User user = null;
while(cursor.moveToNext()){
user = new User();
user.setUserName(cursor.getString(cursor.getColumnIndex(DBHelper.COLNUMNAME)));
user.setUserPass(cursor.getString(cursor.getColumnIndex(DBHelper.COLNUMPASS)));
}
cursor.close();
return user;
}
/**
* 判断是否存在该用户
*
* @param user
* @return
*/
@Override
public boolean isExistsUser(User user) {
User isExit = queryUserByName(user.getUserName());
return isExit == null ? false : true;
}
/**
* 判断是否登录成功
* @param user 登录的用户信息
* @return
*/
@Override
public boolean isLoginSuccess(User user) {
database = dbHelper.getReadableDatabase();
//方法一:sql语句操作
// String sql = "select * from " + DBHelper.TABLENAME + " where " + DBHelper.COLNUMNAME + " = ? and " + DBHelper.COLNUMPASS + " = ?";
// Cursor cursor = database.rawQuery(sql, new String[]{user.getUserName(), user.getUserPass()});
//方法二:封装的api操作,直接操作方法即可
Cursor cursor = database.query(DBHelper.TABLENAME, null, DBHelper.COLNUMNAME + " = ? and " + DBHelper.COLNUMPASS + " = ?", new String[]{user.getUserName(), user.getUserPass()}, null, null, null);
if(cursor.moveToFirst()){
cursor.close();
return true;
}
cursor.close();
return false;
}
}
DBHelper.java
public class DBHelper extends SQLiteOpenHelper {
//数据库名
public static final String DBNAME = "users.db";
//版本号
public static final int VERSION = 1;
//表名
public static final String TABLENAME = "users";
//列名
public static final String COLNUMNAME = "uName";
//列名
public static final String COLNUMPASS = "uPass";
public DBHelper(Context context) {
super(context, DBNAME, null, VERSION);
}
/**
* 该方法只执行一次,首次执行创建表
* @param db
*/
@Override
public void onCreate(SQLiteDatabase db) {
String sql = "create table " + TABLENAME + "(_id integer primary key autoincrement,uName varchar(20) not null,uPass varchar(20) not null)";
db.execSQL(sql);
}
/**
* 版本更新调用该方法
* @param db
* @param oldVersion
* @param newVersion
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
/**
* 还原旧版本
* @param db
* @param oldVersion
* @param newVersion
*/
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
super.onDowngrade(db, oldVersion, newVersion);
}
}
User.java
public class User {
private String userName;
private String userPass;
public User() {
}
public User(String userName, String userPass) {
this.userName = userName;
this.userPass = userPass;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPass() {
return userPass;
}
public void setUserPass(String userPass) {
this.userPass = userPass;
}
@Override
public String toString() {
return "User{" +
"userName='" + userName + '\'' +
", userPass='" + userPass + '\'' +
'}';
}
}
基本的功能都已经实现了,所有的代码都在这里,关于布局的代码就不贴上 ,等下我把整个项目打包一下,需要源代码的直接自己下载就行了。对于不属性MVP模式的童鞋,可能能看懂,但是自己要去实现就有一点点麻烦了,下面看看运行的结果吧。