2022-11-1学习内容
1.优化忘记密码
1.1activity_login_main.xml
<?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"> <RadioGroup android:id="@+id/rg_login" android:layout_width="match_parent" android:layout_height="@dimen/item_layout_height" android:orientation="horizontal"> <RadioButton android:id="@+id/rb_password" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:checked="true" android:text="@string/login_by_password" android:textSize="@dimen/common_font_size" android:textColor="@color/black"/> <RadioButton android:id="@+id/rb_verifycode" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:text="@string/login_by_verifycode" android:textSize="@dimen/common_font_size" android:textColor="@color/black"/> </RadioGroup> <LinearLayout android:layout_width="match_parent" android:layout_height="@dimen/item_layout_height" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:text="@string/phone_number" android:textColor="@color/black" /> <EditText android:id="@+id/et_phone" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:layout_marginTop="5dp" android:layout_marginBottom="5dp" android:background="@drawable/editext_selector" android:hint="@string/input_phone_number" android:inputType="number" android:maxLength="11" android:textColor="@color/grey" android:textSize="@dimen/common_font_size"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="@dimen/item_layout_height" android:orientation="horizontal"> <TextView android:id="@+id/tv_password" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:text="@string/login_password" android:textColor="@color/black" /> <RelativeLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1"> <EditText android:id="@+id/et_password" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="5dp" android:layout_weight="1" android:background="@drawable/editext_selector" android:hint="@string/input_password" android:inputType="numberPassword" android:layout_marginBottom="5dp" android:maxLength="11" android:textColor="@color/grey" android:textSize="@dimen/common_font_size" /> <Button android:id="@+id/btn_forget" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_alignParentEnd="true" android:text="@string/forget_password" android:textColor="@color/black" android:textSize="@dimen/common_font_size" /> </RelativeLayout> </LinearLayout> <CheckBox android:id="@+id/ck_remember" android:layout_width="match_parent" android:layout_height="wrap_content" android:button="@drawable/checkbox_selector" android:text="@string/remember_password" android:textColor="@color/black" android:textSize="@dimen/common_font_size" /> <Button android:id="@+id/btn_login" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/login" android:textColor="@color/black" android:textSize="@dimen/button_font_size" /> </LinearLayout>
1.2LoginDBHelper.java
package com.example.chapter06.database; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import com.example.chapter06.entity.LoginInfo; import com.example.chapter06.entity.User; import java.util.ArrayList; import java.util.List; public class LoginDBHelper extends SQLiteOpenHelper { private static final String DB_NAME = "login.db"; private static final String TABLE_NAME = "LOGIN_INFO"; private static final int DB_VERSION = 1; private static LoginDBHelper mHelper = null; private SQLiteDatabase mRDB = null; private SQLiteDatabase mWDB = null; private LoginDBHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); } // 打开数据库的读连接 public SQLiteDatabase openReadLink() { if (mRDB == null || !mRDB.isOpen()) { mRDB = mHelper.getReadableDatabase(); } return mRDB; } // 打开数据库的写连接 public SQLiteDatabase openWriteLink() { if (mWDB == null || !mWDB.isOpen()) { mWDB = mHelper.getWritableDatabase(); } return mWDB; } // 关闭数据库连接 public void closeLink() { if (mRDB != null && mRDB.isOpen()) { mRDB.close(); mRDB = null; } if (mWDB != null && mWDB.isOpen()) { mWDB.close(); mWDB = null; } } // 利用单例模式获取数据库帮助器的唯一实例 public static LoginDBHelper getInstance(Context context) { if (mHelper == null) { mHelper = new LoginDBHelper(context); } return mHelper; } // 创建数据库,执行建表语句 @Override public void onCreate(SQLiteDatabase db) { String sql = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" + "_ID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," + " PHONE VARCHAR NOT NULL," + " PASSWORD VARCHAR NOT NULL," + " REMEMBER INTEGER NOT NULL);"; db.execSQL(sql); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } public void save(LoginInfo info) { // 如果存在则先删除,再添加 try { mWDB.beginTransaction(); delete(info); insert(info); mWDB.setTransactionSuccessful(); } catch (Exception e) { e.printStackTrace(); } finally { mWDB.endTransaction(); } } public long delete(LoginInfo info) { return mWDB.delete(TABLE_NAME, "PHONE=?", new String[]{info.phone}); } public long insert(LoginInfo loginInfo) { ContentValues values = new ContentValues(); values.put("PHONE", loginInfo.phone); values.put("PASSWORD", loginInfo.password); values.put("REMEMBER", loginInfo.remember); return mWDB.insert(TABLE_NAME, null, values); } public long deleteByName(String name) { // 删除所有 // mWDB.delete(TABLE_NAME, "1=1", null); return mWDB.delete(TABLE_NAME, "NAME=?", new String[]{name}); } public List<User> queryAll() { List<User> list = new ArrayList<>(); // 执行记录查询动作,该语句返回结果集的游标 Cursor cursor = mRDB.query(TABLE_NAME, null, null, null, null, null, null); // 循环取出游标指向的每条记录 while (cursor.moveToNext()) { User user = new User(); user.id = cursor.getInt(0); user.name = cursor.getString(1); user.age = cursor.getInt(2); user.height = cursor.getLong(3); user.weight = cursor.getFloat(4); // SQLite没有布尔型,用0表示false,用1表示true user.married = (cursor.getInt(5) == 0) ? false : true; list.add(user); } return list; } public List<User> queryByName(String name) { List<User> list = new ArrayList<>(); // 执行记录查询动作,该语句返回结果集的游标 Cursor cursor = mRDB.query(TABLE_NAME, null, "NAME=?", new String[]{name}, null, null, null); // 循环取出游标指向的每条记录 while (cursor.moveToNext()) { User user = new User(); user.id = cursor.getInt(0); user.name = cursor.getString(1); user.age = cursor.getInt(2); user.height = cursor.getLong(3); user.weight = cursor.getFloat(4); // SQLite没有布尔型,用0表示false,用1表示true user.married = (cursor.getInt(5) == 0) ? false : true; list.add(user); } return list; } public LoginInfo queryByTop() { LoginInfo info = null; String sql = "SELECT * FROM " + TABLE_NAME + " WHERE REMEMBER = 1 ORDER BY _ID DESC LIMIT 1"; // 执行记录查询动作,该语句返回结果集的游标 Cursor cursor = mRDB.rawQuery(sql, null); if (cursor.moveToNext()) { info = new LoginInfo(); info.id = cursor.getInt(0); info.phone = cursor.getString(1); info.password = cursor.getString(2); // SQLite没有布尔型,用0表示false,用1表示true info.remember = (cursor.getInt(3) == 0) ? false : true; } return info; } public LoginInfo queryByPhone(String phone) { LoginInfo info = null; String sql = "SELECT * FROM " + TABLE_NAME; // 执行记录查询动作,该语句返回结果集的游标 Cursor cursor = mRDB.query(TABLE_NAME, null, "phone=? and remember=1", new String[]{phone}, null, null, null); if (cursor.moveToNext()) { info = new LoginInfo(); info.id = cursor.getInt(0); info.phone = cursor.getString(1); info.password = cursor.getString(2); // SQLite没有布尔型,用0表示false,用1表示true info.remember = (cursor.getInt(3) == 0) ? false : true; } return info; } }
1.3LoginSQLiteActivity.java
package com.example.chapter06; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.TextView; import android.widget.Toast; import androidx.activity.result.ActivityResult; import androidx.activity.result.ActivityResultCallback; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import com.example.chapter06.database.LoginDBHelper; import com.example.chapter06.entity.LoginInfo; import com.example.chapter06.util.ViewUnil; import java.util.Random; public class LoginSQLiteActivity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener, View.OnClickListener, View.OnFocusChangeListener { private TextView tv_password; private EditText et_password; private Button btn_forget; private CheckBox ck_remember; private EditText et_phone; private RadioButton rb_verifycode; private RadioButton rb_password; private ActivityResultLauncher<Intent> register; private Button btn_login; private String mPassword = "111111"; private String mVerifyCode; private SharedPreferences preferences; private LoginDBHelper mHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login_main); RadioGroup rg_login = findViewById(R.id.rg_login); tv_password = findViewById(R.id.tv_password); et_phone = findViewById(R.id.et_phone); et_password = findViewById(R.id.et_password); btn_forget = findViewById(R.id.btn_forget); ck_remember = findViewById(R.id.ck_remember); rb_password = findViewById(R.id.rb_password); rb_verifycode = findViewById(R.id.rb_verifycode); btn_login = findViewById(R.id.btn_login); // 给rg_login设置单选监听器 rg_login.setOnCheckedChangeListener(this); // 给et_phone添加文本变更监听器 et_phone.addTextChangedListener(new HideTextWatcher(et_phone, 11)); // 给et_password添加文本变更监听器 et_password.addTextChangedListener(new HideTextWatcher(et_password, 6)); btn_forget.setOnClickListener(this); btn_login.setOnClickListener(this); register = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() { @Override public void onActivityResult(ActivityResult result) { Intent intent = result.getData(); if (intent != null && result.getResultCode() == Activity.RESULT_OK) { // 用户密码已改为新密码,故更新密码变量 mPassword = intent.getStringExtra("new_password"); } } }); et_password.setOnFocusChangeListener(this); } private void reload() { LoginInfo info = mHelper.queryByTop(); if (info != null && info.remember) { et_phone.setText(info.phone); et_password.setText(info.password); ck_remember.setChecked(true); } // boolean isRember = preferences.getBoolean("isRember", false); // if (isRember) { // String phone = preferences.getString("phone", ""); // String password = preferences.getString("password", ""); // } } @Override protected void onStart() { super.onStart(); mHelper = LoginDBHelper.getInstance(this); mHelper.openReadLink(); mHelper.openWriteLink(); reload(); } @Override protected void onStop() { super.onStop(); mHelper.closeLink(); } @Override public void onCheckedChanged(RadioGroup group, int checkedId) { switch (checkedId) { // 选择了密码登录 case R.id.rb_password: tv_password.setText(getString(R.string.login_password)); et_password.setHint(getString(R.string.input_password)); btn_forget.setText(getString(R.string.forget_password)); ck_remember.setVisibility(View.VISIBLE); break; // 选择了验证码登录 case R.id.rb_verifycode: tv_password.setText(getString(R.string.verifycode)); et_password.setHint(getString(R.string.input_verifycode)); btn_forget.setText(getString(R.string.get_verifycode)); ck_remember.setVisibility(View.GONE); break; } } @Override public void onClick(View v) { String phone = et_phone.getText().toString(); if (phone.length() < 11) { Toast.makeText(this, "请输入正确的手机号", Toast.LENGTH_SHORT).show(); return; } switch(v.getId()) { case R.id.btn_forget: // 选择了密码方式校验,此时要跳到找回密码页面 if (rb_password.isChecked()) { // 以下携带手机号码跳转到找回密码页面 Intent intent = new Intent(this, LoginForgetActivity.class); intent.putExtra("phone", phone); register.launch(intent); } else if (rb_verifycode.isChecked()) { // 生成六位随机数字的验证码 mVerifyCode = String.format("%06d", new Random().nextInt(999999)); // 以下弹出提醒对话框,提示用户记住六位验证码数字 AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("请记住验证码"); builder.setMessage("手机号" + phone + ",本次验证码是" + mVerifyCode + ",请输入验证码"); builder.setPositiveButton("好的", null); AlertDialog dialog = builder.create(); dialog.show(); } break; case R.id.btn_login: // 密码方式校验 if (rb_password.isChecked()) { if (!mPassword.equals(et_password.getText().toString())) { Toast.makeText(this, "请输入正确的密码", Toast.LENGTH_SHORT).show(); return; } // 提示用户登录成功 loginSuccess(); } else if (rb_verifycode.isChecked()) { // 验证码方式校验 if (!mPassword.equals(et_password.getText().toString())) { Toast.makeText(this, "请输入正确的验证码", Toast.LENGTH_SHORT).show(); return; } // 提示用户登录成功 loginSuccess(); } break; } } private void loginSuccess() { String desc = String.format("您的手机号码是%s,恭喜你通过登录验证,点击“确定“按钮返回上个页面", et_phone.getText().toString()); // 以下弹出提醒对话框,提示用户登录成功 AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("登录成功"); builder.setMessage(desc); builder.setPositiveButton("确定返回", (dialog, which) -> { // 结束当前的活动页面 finish(); }); builder.setNegativeButton("我再看看", null); AlertDialog dialog = builder.create(); dialog.show(); // 保存到数据库 LoginInfo info = new LoginInfo(); info.phone = et_phone.getText().toString(); info.password =et_password.getText().toString(); info.remember = ck_remember.isChecked(); mHelper.save(info); } // 当密码输入框获取焦点之后,根据输入的电话号码,查询出对应的密码,自动填入 @Override public void onFocusChange(View v, boolean hasFocus) { if (v.getId() == R.id.et_password && hasFocus) { LoginInfo info = mHelper.queryByPhone(et_phone.getText().toString()); // 如果根据电话号码,查询出了密码 if (info != null) { et_password.setText(info.password); ck_remember.setChecked(info.remember); } else { // 没有查到,清空密码 et_password.setText(""); ck_remember.setChecked(false); } } } // 定义一个编辑框监听器,在输入文本达到指定长度时自动隐藏输入法 private class HideTextWatcher implements TextWatcher { private EditText mView; private int maxLength; public HideTextWatcher(EditText v, int maxLength) { this.mView = v; this.maxLength = maxLength; } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { if (s.toString().length() == maxLength) { // 隐藏输入法软键盘 ViewUnil.hideOneInputMethod(LoginSQLiteActivity.this, mView); } } } }
1.4效果
点击记住密码,然后点击登录:
可以看到SQLlite数据库中插入了一条记录:
对于已选择“记住密码”的手机号,当“登录密码”输入框获取到焦点事件时,自动查数据库获取登录密码:
对于未选择“记住密码”的手机号,即使“登录密码”输入框获取到焦点事件,也不会查数据库获取登录密码: