Android studio內置數(shù)據(jù)庫sqLite的使用指南
任何軟件的開發(fā),都離不開數(shù)據(jù)庫的使用,你使用的各個軟件的用戶信息都儲存在后端的數(shù)據(jù)庫中,上次我們講了后端springboot+mybatis+postersql的使用連接方法,但其實,Android studio在安裝時有一個快捷簡便的數(shù)據(jù)庫sqLite他以輕便快捷著稱。
1.基本概念
1)SQLite是什么?為什么要用SQLite?SQLite有什么特點?
答:下面請聽小豬娓娓道來:
①SQLite是一個輕量級的關系型數(shù)據(jù)庫,運算速度快,占用資源少,很適合在移動設備上使用, 不僅支持標準SQL語法,還遵循ACID(數(shù)據(jù)庫事務)原則,無需賬號,使用起來非常方便!
②前面我們學習了使用文件與SharedPreference來保存數(shù)據(jù),但是在很多情況下, 文件并不一定是有效的,如多線程并發(fā)訪問是相關的;app要處理可能變化的復雜數(shù)據(jù)結構等等! 比如銀行的存錢與取錢!使用前兩者就會顯得很無力或者繁瑣,數(shù)據(jù)庫的出現(xiàn)可以解決這種問題, 而Android又給我們提供了這樣一個輕量級的SQLite,為何不用?
③SQLite支持五種數(shù)據(jù)類型:NULL,INTEGER,REAL(浮點數(shù)),TEXT(字符串文本)和BLOB(二進制對象) 雖然只有五種,但是對于varchar,char等其他數(shù)據(jù)類型都是可以保存的;因為SQLite有個最大的特點: 你可以各種數(shù)據(jù)類型的數(shù)據(jù)保存到任何字段中而不用關心字段聲明的數(shù)據(jù)類型是什么,比如你 可以在Integer類型的字段中存放字符串,當然除了聲明為主鍵INTEGER PRIMARY KEY的字段只能夠存儲64位整數(shù)! 另外, SQLite 在解析CREATE TABLE 語句時, 會忽略 CREATE TABLE 語句中跟在字段名后面的數(shù)據(jù)類型信息如下面語句會忽略 name字段的類型信息: CREATE TABLE person (personid integer primary key autoincrement, name varchar(20))
小結下特點:
SQlite通過文件來保存數(shù)據(jù)庫,一個文件就是一個數(shù)據(jù)庫,數(shù)據(jù)庫中又包含多個表格,表格里又有 多條記錄,每個記錄由多個字段構成,每個字段有對應的值,每個值我們可以指定類型,也可以不指定 類型(主鍵除外)
2)幾個相關的類:
SQLiteOpenHelper:抽象類,我們通過繼承該類,然后重寫數(shù)據(jù)庫創(chuàng)建以及更新的方法, 我們還可以通過該類的對象獲得數(shù)據(jù)庫實例,或者關閉數(shù)據(jù)庫!
SQLiteDatabase:數(shù)據(jù)庫訪問類:我們可以通過該類的對象來對數(shù)據(jù)庫做一些增刪改查的操作
Cursor:游標,有點類似于JDBC里的resultset,結果集!可以簡單理解為指向數(shù)據(jù)庫中某 一個記錄的指針!
3)代碼示例:
用sqlite做一個登錄頁面,包括記住密碼,重置密碼,發(fā)送驗證碼
userinfo類,
設定一些對象應有的屬性:
package com.example.jhjh;
//用戶信息
public class UserInfo {
public long rowid; // 行號
public int xuhao; // 序號
public String name; // 姓名
public int age; // 年齡
public long height; // 身高
public float weight; // 體重
public boolean married; // 婚否
public String update_time; // 更新時間
public String phone; // 手機號
public String password; // 密碼
public UserInfo() {
rowid = 0L;
xuhao = 0;
name = "";
age = 0;
height = 0L;
weight = 0.0f;
married = false;
update_time = "";
phone = "";
password = "";
}
}UserDBhelper類
用來調用數(shù)據(jù)及數(shù)據(jù)庫的一些操作
package com.example.jhjh;
import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import com.example.jhjh.UserInfo;
import java.util.ArrayList;
import java.util.List;
@SuppressLint("DefaultLocale")
public class UserDBHelper extends SQLiteOpenHelper {
private static final String TAG = "UserDBHelper";
private static final String DB_NAME = "user.db"; // 數(shù)據(jù)庫的名稱
private static final int DB_VERSION = 1; // 數(shù)據(jù)庫的版本號
private static UserDBHelper mHelper = null; // 數(shù)據(jù)庫幫助器的實例
private SQLiteDatabase mDB = null; // 數(shù)據(jù)庫的實例
public static final String TABLE_NAME = "user_info"; // 表的名稱
private UserDBHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
private UserDBHelper(Context context, int version) {
super(context, DB_NAME, null, version);
}
// 利用單例模式獲取數(shù)據(jù)庫幫助器的唯一實例
public static UserDBHelper getInstance(Context context, int version) {
if (version > 0 && mHelper == null) {
mHelper = new UserDBHelper(context, version);
} else if (mHelper == null) {
mHelper = new UserDBHelper(context);
}
return mHelper;
}
// 打開數(shù)據(jù)庫的讀連接
public SQLiteDatabase openReadLink() {
if (mDB == null || !mDB.isOpen()) {
mDB = mHelper.getReadableDatabase();
}
return mDB;
}
// 打開數(shù)據(jù)庫的寫連接
public SQLiteDatabase openWriteLink() {
if (mDB == null || !mDB.isOpen()) {
mDB = mHelper.getWritableDatabase();
}
return mDB;
}
// 關閉數(shù)據(jù)庫連接
public void closeLink() {
if (mDB != null && mDB.isOpen()) {
mDB.close();
mDB = null;
}
}
// 創(chuàng)建數(shù)據(jù)庫,執(zhí)行建表語句
public void onCreate(SQLiteDatabase db) {
Log.d(TAG, "onCreate");
String drop_sql = "DROP TABLE IF EXISTS " + TABLE_NAME + ";";
Log.d(TAG, "drop_sql:" + drop_sql);
db.execSQL(drop_sql);
String create_sql = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " ("
+ "_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
+ "name VARCHAR NOT NULL," + "age INTEGER NOT NULL,"
+ "height INTEGER NOT NULL," + "weight FLOAT NOT NULL,"
+ "married INTEGER NOT NULL," + "update_time VARCHAR NOT NULL"
//演示數(shù)據(jù)庫升級時要先把下面這行注釋
+ ",phone VARCHAR" + ",password VARCHAR"
+ ");";
Log.d(TAG, "create_sql:" + create_sql);
db.execSQL(create_sql); // 執(zhí)行完整的SQL語句
}
// 升級數(shù)據(jù)庫,執(zhí)行表結構變更語句
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.d(TAG, "onUpgrade oldVersion=" + oldVersion + ", newVersion=" + newVersion);
if (newVersion > 1) {
//Android的ALTER命令不支持一次添加多列,只能分多次添加
String alter_sql = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + "phone VARCHAR;";
Log.d(TAG, "alter_sql:" + alter_sql);
db.execSQL(alter_sql);
alter_sql = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN " + "password VARCHAR;";
Log.d(TAG, "alter_sql:" + alter_sql);
db.execSQL(alter_sql); // 執(zhí)行完整的SQL語句
}
}
// 根據(jù)指定條件刪除表記錄
public int delete(String condition) {
// 執(zhí)行刪除記錄動作,該語句返回刪除記錄的數(shù)目
return mDB.delete(TABLE_NAME, condition, null);
}
// 刪除該表的所有記錄
public int deleteAll() {
// 執(zhí)行刪除記錄動作,該語句返回刪除記錄的數(shù)目
return mDB.delete(TABLE_NAME, "1=1", null);
}
// 往該表添加一條記錄
public long insert(UserInfo info) {
List<UserInfo> infoList = new ArrayList<UserInfo>();
infoList.add(info);
return insert(infoList);
}
// 往該表添加多條記錄
public long insert(List<UserInfo> infoList) {
long result = -1;
for (int i = 0; i < infoList.size(); i++) {
UserInfo info = infoList.get(i);
List<UserInfo> tempList = new ArrayList<UserInfo>();
// 如果存在同名記錄,則更新記錄
// 注意條件語句的等號后面要用單引號括起來
if (info.name != null && info.name.length() > 0) {
String condition = String.format("name='%s'", info.name);
tempList = query(condition);
if (tempList.size() > 0) {
update(info, condition);
result = tempList.get(0).rowid;
continue;
}
}
// 如果存在同樣的手機號碼,則更新記錄
if (info.phone != null && info.phone.length() > 0) {
String condition = String.format("phone='%s'", info.phone);
tempList = query(condition);
if (tempList.size() > 0) {
update(info, condition);
result = tempList.get(0).rowid;
continue;
}
}
// 不存在唯一性重復的記錄,則插入新記錄
ContentValues cv = new ContentValues();
cv.put("name", info.name);
cv.put("age", info.age);
cv.put("height", info.height);
cv.put("weight", info.weight);
cv.put("married", info.married);
cv.put("update_time", info.update_time);
cv.put("phone", info.phone);
cv.put("password", info.password);
// 執(zhí)行插入記錄動作,該語句返回插入記錄的行號
result = mDB.insert(TABLE_NAME, "", cv);
if (result == -1) { // 添加成功則返回行號,添加失敗則返回-1
return result;
}
}
return result;
}
// 根據(jù)條件更新指定的表記錄
public int update(UserInfo info, String condition) {
ContentValues cv = new ContentValues();
cv.put("name", info.name);
cv.put("age", info.age);
cv.put("height", info.height);
cv.put("weight", info.weight);
cv.put("married", info.married);
cv.put("update_time", info.update_time);
cv.put("phone", info.phone);
cv.put("password", info.password);
// 執(zhí)行更新記錄動作,該語句返回更新的記錄數(shù)量
return mDB.update(TABLE_NAME, cv, condition, null);
}
public int update(UserInfo info) {
// 執(zhí)行更新記錄動作,該語句返回更新的記錄數(shù)量
return update(info, "rowid=" + info.rowid);
}
// 根據(jù)指定條件查詢記錄,并返回結果數(shù)據(jù)列表
public List<UserInfo> query(String condition) {
String sql = String.format("select rowid,_id,name,age,height," +
"weight,married,update_time,phone,password " +
"from %s where %s;", TABLE_NAME, condition);
Log.d(TAG, "query sql: " + sql);
List<UserInfo> infoList = new ArrayList<UserInfo>();
// 執(zhí)行記錄查詢動作,該語句返回結果集的游標
Cursor cursor = mDB.rawQuery(sql, null);
// 循環(huán)取出游標指向的每條記錄
while (cursor.moveToNext()) {
UserInfo info = new UserInfo();
info.rowid = cursor.getLong(0); // 取出長整型數(shù)
info.xuhao = cursor.getInt(1); // 取出整型數(shù)
info.name = cursor.getString(2); // 取出字符串
info.age = cursor.getInt(3); // 取出整型數(shù)
info.height = cursor.getLong(4); // 取出長整型數(shù)
info.weight = cursor.getFloat(5); // 取出浮點數(shù)
//SQLite沒有布爾型,用0表示false,用1表示true
info.married = (cursor.getInt(6) == 0) ? false : true;
info.update_time = cursor.getString(7); // 取出字符串
info.phone = cursor.getString(8); // 取出字符串
info.password = cursor.getString(9); // 取出字符串
infoList.add(info);
}
cursor.close(); // 查詢完畢,關閉數(shù)據(jù)庫游標
return infoList;
}
// 根據(jù)手機號碼查詢指定記錄
public UserInfo queryByPhone(String phone) {
UserInfo info = null;
List<UserInfo> infoList = query(String.format("phone='%s'", phone));
if (infoList.size() > 0) { // 存在該號碼的登錄信息
info = infoList.get(0);
}
return info;
}
}Dateuitl類:
用來獲取實時時間
package com.example.jhjh;
import android.annotation.SuppressLint;
import android.text.TextUtils;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
@SuppressLint("SimpleDateFormat")
public class DateUtil {
// 獲取當前的日期時間
public static String getNowDateTime(String formatStr) {
String format = formatStr;
if (TextUtils.isEmpty(format)) {
format = "yyyyMMddHHmmss";
}
SimpleDateFormat sdf = new SimpleDateFormat(format);
return sdf.format(new Date());
}
// 獲取當前的時間
public static String getNowTime() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
return sdf.format(new Date());
}
// 獲取當前的時間(精確到毫秒)
public static String getNowTimeDetail() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
return sdf.format(new Date());
}
public static String formatDate(long time) {
Date date = new Date(time);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(date);
}
}密碼登錄的activity
LoginSQLiteActivity .java
package com.example.jhjh;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.View.OnFocusChangeListener;
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.appcompat.app.AppCompatActivity;
import com.example.jhjh.UserInfo;
import com.example.jhjh.UserDBHelper;
import com.example.jhjh.DateUtil;
import com.example.jhjh.ViewUtil;
import java.util.Random;
@SuppressLint("DefaultLocale")
public class LoginSQLiteActivity extends AppCompatActivity implements View.OnClickListener, OnFocusChangeListener {
private RadioGroup rg_login; // 聲明一個單選組對象
private RadioButton rb_password; // 聲明一個單選按鈕對象
private RadioButton rb_verifycode; // 聲明一個單選按鈕對象
private EditText et_phone; // 聲明一個編輯框對象
private TextView tv_password; // 聲明一個文本視圖對象
private EditText et_password; // 聲明一個編輯框對象
private Button btn_forget; // 聲明一個按鈕控件對象
private CheckBox ck_remember; // 聲明一個復選框對象
private int mRequestCode = 0; // 跳轉頁面時的請求代碼
private boolean isRemember = false; // 是否記住密碼
private String mPassword = "111111"; // 默認密碼
private String mVerifyCode; // 驗證碼
private UserDBHelper mHelper; // 聲明一個用戶數(shù)據(jù)庫的幫助器對象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login_sqlite);
rg_login = findViewById(R.id.rg_login);
rb_password = findViewById(R.id.rb_password);
rb_verifycode = findViewById(R.id.rb_verifycode);
et_phone = findViewById(R.id.et_phone);
tv_password = findViewById(R.id.tv_password);
et_password = findViewById(R.id.et_password);
btn_forget = findViewById(R.id.btn_forget);
ck_remember = findViewById(R.id.ck_remember);
// 給rg_login設置單選監(jiān)聽器
rg_login.setOnCheckedChangeListener(new RadioListener());
// 給ck_remember設置勾選監(jiān)聽器
ck_remember.setOnCheckedChangeListener((buttonView, isChecked) -> isRemember = isChecked);
// 給et_phone添加文本變更監(jiān)聽器
et_phone.addTextChangedListener(new HideTextWatcher(et_phone, 11));
// 給et_password添加文本變更監(jiān)聽器
et_password.addTextChangedListener(new HideTextWatcher(et_password, 6));
btn_forget.setOnClickListener(this);
findViewById(R.id.btn_login).setOnClickListener(this);
// 給密碼編輯框注冊一個焦點變化監(jiān)聽器,一旦焦點發(fā)生變化,就觸發(fā)監(jiān)聽器的onFocusChange方法
et_password.setOnFocusChangeListener(this);
}
// 定義登錄方式的單選監(jiān)聽器
private class RadioListener implements RadioGroup.OnCheckedChangeListener {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (checkedId == R.id.rb_password) { // 選擇了密碼登錄
tv_password.setText("登錄密碼:");
et_password.setHint("請輸入密碼");
btn_forget.setText("忘記密碼");
ck_remember.setVisibility(View.VISIBLE);
} else if (checkedId == R.id.rb_verifycode) { // 選擇了驗證碼登錄
tv_password.setText(" 驗證碼:");
et_password.setHint("請輸入驗證碼");
btn_forget.setText("獲取驗證碼");
ck_remember.setVisibility(View.GONE);
}
}
}
// 定義一個編輯框監(jiān)聽器,在輸入文本達到指定長度時自動隱藏輸入法
private class HideTextWatcher implements TextWatcher {
private EditText mView; // 聲明一個編輯框對象
private int mMaxLength; // 聲明一個最大長度變量
public HideTextWatcher(EditText v, int maxLength) {
super();
mView = v;
mMaxLength = maxLength;
}
// 在編輯框的輸入文本變化前觸發(fā)
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
// 在編輯框的輸入文本變化時觸發(fā)
public void onTextChanged(CharSequence s, int start, int before, int count) {}
// 在編輯框的輸入文本變化后觸發(fā)
public void afterTextChanged(Editable s) {
String str = s.toString(); // 獲得已輸入的文本字符串
// 輸入文本達到11位(如手機號碼),或者達到6位(如登錄密碼)時關閉輸入法
if ((str.length() == 11 && mMaxLength == 11)
|| (str.length() == 6 && mMaxLength == 6)) {
ViewUtil.hideOneInputMethod(LoginSQLiteActivity.this, mView); // 隱藏輸入法軟鍵盤
}
}
}
@Override
public void onClick(View v) {
String phone = et_phone.getText().toString();
if (v.getId() == R.id.btn_forget) { // 點擊了“忘記密碼”按鈕
if (phone.length() < 11) { // 手機號碼不足11位
Toast.makeText(this, "請輸入正確的手機號", Toast.LENGTH_SHORT).show();
return;
}
if (rb_password.isChecked()) { // 選擇了密碼方式校驗,此時要跳到找回密碼頁面
// 以下攜帶手機號碼跳轉到找回密碼頁面
Intent intent = new Intent(this, LoginForgetActivity.class);
intent.putExtra("phone", phone);
startActivityForResult(intent, mRequestCode); // 攜帶意圖返回上一個頁面
} else if (rb_verifycode.isChecked()) { // 選擇了驗證碼方式校驗,此時要生成六位隨機數(shù)字驗證碼
// 生成六位隨機數(shù)字的驗證碼
mVerifyCode = String.format("%06d", new Random().nextInt(999999));
// 以下彈出提醒對話框,提示用戶記住六位驗證碼數(shù)字
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("請記住驗證碼");
builder.setMessage("手機號" + phone + ",本次驗證碼是" + mVerifyCode + ",請輸入驗證碼");
builder.setPositiveButton("好的", null);
AlertDialog alert = builder.create();
alert.show(); // 顯示提醒對話框
}
} else if (v.getId() == R.id.btn_login) { // 點擊了“登錄”按鈕
if (phone.length() < 11) { // 手機號碼不足11位
Toast.makeText(this, "請輸入正確的手機號", Toast.LENGTH_SHORT).show();
return;
}
if (rb_password.isChecked()) { // 密碼方式校驗
if (!et_password.getText().toString().equals(mPassword)) {
Toast.makeText(this, "請輸入正確的密碼", Toast.LENGTH_SHORT).show();
} else { // 密碼校驗通過
loginSuccess(); // 提示用戶登錄成功
}
} else if (rb_verifycode.isChecked()) { // 驗證碼方式校驗
if (!et_password.getText().toString().equals(mVerifyCode)) {
Toast.makeText(this, "請輸入正確的驗證碼", Toast.LENGTH_SHORT).show();
} else { // 驗證碼校驗通過
loginSuccess(); // 提示用戶登錄成功
}
}
}
}
// 從下一個頁面攜帶參數(shù)返回當前頁面時觸發(fā)
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == mRequestCode && data != null) {
// 用戶密碼已改為新密碼,故更新密碼變量
mPassword = data.getStringExtra("new_password");
}
}
// 從修改密碼頁面返回登錄頁面,要清空密碼的輸入框
@Override
protected void onRestart() {
super.onRestart();
et_password.setText("");
}
@Override
protected void onResume() {
super.onResume();
mHelper = UserDBHelper.getInstance(this, 1); // 獲得用戶數(shù)據(jù)庫幫助器的實例
mHelper.openWriteLink(); // 恢復頁面,則打開數(shù)據(jù)庫連接
}
@Override
protected void onPause() {
super.onPause();
mHelper.closeLink(); // 暫停頁面,則關閉數(shù)據(jù)庫連接
}
// 校驗通過,登錄成功
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 alert = builder.create();
alert.show();
// 如果勾選了“記住密碼”,則把手機號碼和密碼保存為數(shù)據(jù)庫的用戶表記錄
if (isRemember) {
UserInfo info = new UserInfo(); // 創(chuàng)建一個用戶信息對象
info.phone = et_phone.getText().toString();
info.password = et_password.getText().toString();
info.update_time = DateUtil.getNowDateTime("yyyy-MM-dd HH:mm:ss");
mHelper.insert(info); // 往用戶數(shù)據(jù)庫添加登錄成功的用戶信息
}
}
// 焦點變更事件的處理方法,hasFocus表示當前控件是否獲得焦點。
// 為什么光標進入密碼框事件不選onClick?因為要點兩下才會觸發(fā)onClick動作(第一下是切換焦點動作)
@Override
public void onFocusChange(View v, boolean hasFocus) {
String phone = et_phone.getText().toString();
// 判斷是否是密碼編輯框發(fā)生焦點變化
if (v.getId() == R.id.et_password) {
// 用戶已輸入手機號碼,且密碼框獲得焦點
if (phone.length() > 0 && hasFocus) {
// 根據(jù)手機號碼到數(shù)據(jù)庫中查詢用戶記錄
UserInfo info = mHelper.queryByPhone(phone);
if (info != null) {
// 找到用戶記錄,則自動在密碼框中填寫該用戶的密碼
et_password.setText(info.password);
}
}
}
}
}xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="5dp" >
<RadioGroup
android:id="@+id/rg_login"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal" >
<RadioButton
android:id="@+id/rb_password"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:checked="true"
android:gravity="left|center"
android:text="密碼登錄"
android:textColor="@color/black"
android:textSize="17sp" />
<RadioButton
android:id="@+id/rb_verifycode"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:checked="false"
android:gravity="left|center"
android:text="驗證碼登錄"
android:textColor="@color/black"
android:textSize="17sp" />
</RadioGroup>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp" >
<TextView
android:id="@+id/tv_phone"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:gravity="center"
android:text="手機號碼:"
android:textColor="@color/black"
android:textSize="17sp" />
<EditText
android:id="@+id/et_phone"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:layout_toRightOf="@+id/tv_phone"
android:gravity="left|center"
android:hint="請輸入手機號碼"
android:inputType="number"
android:maxLength="11"
android:textColor="@color/black"
android:textSize="17sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp" >
<TextView
android:id="@+id/tv_password"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:gravity="center"
android:text="登錄密碼:"
android:textColor="@color/black"
android:textSize="17sp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="@+id/tv_password" >
<EditText
android:id="@+id/et_password"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:gravity="left|center"
android:hint="請輸入密碼"
android:inputType="numberPassword"
android:maxLength="6"
android:textColor="@color/black"
android:textSize="17sp" />
<Button
android:id="@+id/btn_forget"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:gravity="center"
android:text="忘記密碼"
android:textColor="@color/black"
android:textSize="17sp" />
</RelativeLayout>
</RelativeLayout>
<CheckBox
android:id="@+id/ck_remember"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked="false"
android:padding="10dp"
android:text="記住密碼"
android:textColor="@color/black"
android:textSize="17sp" />
<Button
android:id="@+id/btn_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="登 錄"
android:textColor="@color/black"
android:textSize="20sp" />
</LinearLayout>效果圖:

有關忘記密碼后通過驗證碼的代碼:
LoginForgetActivity.activity.java:
package com.example.jhjh;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.Random;
@SuppressLint("DefaultLocale")
public class LoginForgetActivity extends AppCompatActivity implements View.OnClickListener {
private EditText et_password_first; // 聲明一個編輯框對象
private EditText et_password_second; // 聲明一個編輯框對象
private EditText et_verifycode; // 聲明一個編輯框對象
private String mVerifyCode; // 驗證碼
private String mPhone; // 手機號碼
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login_forget);
// 從布局文件中獲取名叫et_password_first的編輯框
et_password_first = findViewById(R.id.et_password_first);
// 從布局文件中獲取名叫et_password_second的編輯框
et_password_second = findViewById(R.id.et_password_second);
// 從布局文件中獲取名叫et_verifycode的編輯框
et_verifycode = findViewById(R.id.et_verifycode);
findViewById(R.id.btn_verifycode).setOnClickListener(this);
findViewById(R.id.btn_confirm).setOnClickListener(this);
// 從上一個頁面獲取要修改密碼的手機號碼
mPhone = getIntent().getStringExtra("phone");
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.btn_verifycode) { // 點擊了“獲取驗證碼”按鈕
if (mPhone == null || mPhone.length() < 11) {
Toast.makeText(this, "請輸入正確的手機號", Toast.LENGTH_SHORT).show();
return;
}
// 生成六位隨機數(shù)字的驗證碼
mVerifyCode = String.format("%06d", new Random().nextInt(999999));
// 以下彈出提醒對話框,提示用戶記住六位驗證碼數(shù)字
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("請記住驗證碼");
builder.setMessage("手機號" + mPhone + ",本次驗證碼是" + mVerifyCode + ",請輸入驗證碼");
builder.setPositiveButton("好的", null);
AlertDialog alert = builder.create();
alert.show(); // 顯示提醒對話框
} else if (v.getId() == R.id.btn_confirm) { // 點擊了“確定”按鈕
String password_first = et_password_first.getText().toString();
String password_second = et_password_second.getText().toString();
if (password_first.length() < 6 || password_second.length() < 6) {
Toast.makeText(this, "請輸入正確的新密碼", Toast.LENGTH_SHORT).show();
return;
}
if (!password_first.equals(password_second)) {
Toast.makeText(this, "兩次輸入的新密碼不一致", Toast.LENGTH_SHORT).show();
return;
}
if (!et_verifycode.getText().toString().equals(mVerifyCode)) {
Toast.makeText(this, "請輸入正確的驗證碼", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "密碼修改成功", Toast.LENGTH_SHORT).show();
// 以下把修改好的新密碼返回給上一個頁面
Intent intent = new Intent(); // 創(chuàng)建一個新意圖
intent.putExtra("new_password", password_first); // 存入新密碼
setResult(Activity.RESULT_OK, intent); // 攜帶意圖返回上一個頁面
finish(); // 結束當前的活動頁面
}
}
}
}xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="5dp" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp" >
<TextView
android:id="@+id/tv_password_first"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="輸入新密碼:"
android:textColor="@color/black"
android:textSize="17sp" />
<EditText
android:id="@+id/et_password_first"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:layout_toRightOf="@+id/tv_password_first"
android:gravity="left|center"
android:hint="請輸入新密碼"
android:inputType="numberPassword"
android:maxLength="11"
android:textColor="@color/black"
android:textSize="17sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp" >
<TextView
android:id="@+id/tv_password_second"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="確認新密碼:"
android:textColor="@color/black"
android:textSize="17sp" />
<EditText
android:id="@+id/et_password_second"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:layout_toRightOf="@+id/tv_password_second"
android:gravity="left|center"
android:hint="請再次輸入新密碼"
android:inputType="numberPassword"
android:maxLength="11"
android:textColor="@color/black"
android:textSize="17sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp" >
<TextView
android:id="@+id/tv_verifycode"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text=" 驗證碼:"
android:textColor="@color/black"
android:textSize="17sp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="@+id/tv_verifycode" >
<EditText
android:id="@+id/et_verifycode"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:gravity="left|center"
android:hint="請輸入驗證碼"
android:inputType="numberPassword"
android:maxLength="6"
android:textColor="@color/black"
android:textSize="17sp" />
<Button
android:id="@+id/btn_verifycode"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:gravity="center"
android:text="獲取驗證碼"
android:textColor="@color/black"
android:textSize="17sp" />
</RelativeLayout>
</RelativeLayout>
<Button
android:id="@+id/btn_confirm"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="確 定"
android:textColor="@color/black"
android:textSize="20sp" />
</LinearLayout>效果圖:

最終效果:



這樣,一個登錄的數(shù)據(jù)庫和通過驗證碼找回密碼的系統(tǒng)就做好了。
到此這篇關于Android studio內置數(shù)據(jù)庫sqLite的使用指南的文章就介紹到這了,更多相關Android studio sqLite使用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- android?studio數(shù)據(jù)存儲建立SQLite數(shù)據(jù)庫實現(xiàn)增刪查改
- Android Studio連接SQLite數(shù)據(jù)庫的登錄注冊實現(xiàn)
- android studio3.0以上如何通過navicat訪問SQLite數(shù)據(jù)庫文件
- Android Studio如何獲取SQLite數(shù)據(jù)并顯示到ListView上
- android studio使用SQLiteOpenHelper()建立數(shù)據(jù)庫的方法
- Android Studio 通過登錄功能介紹SQLite數(shù)據(jù)庫的使用流程
- SQLiteStudio優(yōu)雅調試Android手機數(shù)據(jù)庫Sqlite(推薦)
相關文章
android 中 SQLiteOpenHelper的封裝使用詳解
這篇文章主要介紹了android 中 SQLiteOpenHelper的封裝使用詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-02-02
android真機調試時無法顯示logcat信息的解決方法介紹
以下是對android真機調試時無法顯示logcat信息的解決方法進行了詳細的分析介紹,需要的朋友可以過來參考下2013-07-07
Android 老生常談LayoutInflater的新認知
今天不想去聊一些Android的新功能,新特性之類的東西,特別想聊一聊這個老生常談的話題:LayoutInflater,感興趣的朋友來看看吧2022-03-03
Android Activity與Service通信(不同進程之間)詳解
這篇文章主要介紹了Android Activity與Service通信(不同進程之間)的相關資料,這里提供了三種方法,需要的朋友可以參考下2016-10-10
淺析Android企業(yè)級開發(fā)數(shù)據(jù)綁定技術
這篇文章通過代碼實例分析了Android企業(yè)級開發(fā)數(shù)據(jù)綁定技術的應用以及相關的原理知識,跟著小編一起學習參考下吧。2017-12-12

