Android之SqliteDatabase(MVP模式)實現用戶登錄註冊功能
用戶登錄以及註冊功能的普遍使用就不用我說了,任何一款應用軟件基本都具有登錄和註冊功能,今天通過前面的學習,我寫了一個小demo,就是使用MVP模式寫一個用戶登錄和註冊的功能。有關MVP模式我就不做講解了,通常來說很多實現的登錄或者註冊功能都是使用MVC的模式來實現的,今天我將採用MVP模式來實現這個小demo,主要是爲了鞏固數據庫部分的知識點,然後讓大家熟悉MVP這種模式,看看MVP模式的優勢在哪裏(其實MVP最主要的就是達到完全解耦,不同的層實現不同的功能,互不影響)。
案例的主要功能:
1. 用戶登錄
2. 用戶註冊
模擬場景:當用戶點擊登錄按鈕時,模式了一個延時3秒的操作,相當於從服務器獲取用戶登錄信息,3秒後返回登錄結果。註冊也是一樣
程序整體結構圖:
老樣子,主要功能在程序中註釋
view層:
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層:
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);
}
});
}
}
model層:
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);
}
}
}
dao:(數據庫的操作工具類)
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;
}
}
database:(數據庫封裝類)
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);
}
}
bean:
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模式的童鞋,可能能看懂,但是自己要去實現就有一點點麻煩了,下面看看運行的結果吧。