這是【Android學習之路】之從零開始做一個小項目的階段性代碼展示,目前也實現很多功能啦,待該學期結束後會繼續更新,歡迎閱讀~
寫在前面
該安卓小項目是我在近期正式自學1個月左右後完成的,算是對自己的一個考驗,同時也是對自己這學期數據庫課程的一個收穫的體現叭😊
目前階段的項目源代碼已經上傳至github:SchoolSystem
該APP有一個演示視頻哦~是我第一次這麼正式地錄製講解視頻,嘻嘻,而且目前技術還挺菜的,需要繼續努力💪
視頻發佈在B站上,傳送:https://www.bilibili.com/video/bv1fD4y1D7P6
目前該項目中應該存在很多代碼的冗餘和寫的不好的地方,正在改進中~
因爲最近學校要期末考啦,所以就先做到這裏,其實,目前的進度下可參考借鑑的代碼並不多,主要是思想吧我覺得,如果有小夥伴對其中的某一部分感興趣可以發郵件給我一起探討,我看到之後會及時回覆的 ~
我的郵箱:[email protected]
希望大家能一起學習、交流,共同進步!
界面及功能部分
界面可分爲初始頁面(歡迎頁面)、登錄頁面(管理員、教師、學生)、註冊頁面(教師、學生)、管理員管理頁面(班主任、任課老師、學生、班級)、忘記密碼頁面、登陸成功後的主頁面(分成四個:我的、計劃、學習、論壇)
當然每個頁面的相應功能點擊後會跳轉至新的頁面,這裏就不做一一例舉啦,我按類型來進行展示:
① 初始頁面:
初始頁面Activity關鍵代碼:
//初始登錄界面,由此選擇老師端、學生端或是管理員
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_init);
RelativeLayout chooseTeacher = (RelativeLayout) findViewById(R.id.ChooseTeacher);
chooseTeacher.setOnClickListener(new JumpTeacher()); //教師登錄頁面跳轉
RelativeLayout chooseStudent = (RelativeLayout) findViewById(R.id.ChooseStudent);
chooseStudent.setOnClickListener(new JumpStudent()); //學生登錄頁面跳轉
RelativeLayout chooseAdmin = (RelativeLayout) findViewById(R.id.ChooseAdmin);
chooseAdmin.setOnClickListener(new JumpAdmin()); //管理員頁面跳轉
}
private class JumpTeacher implements View.OnClickListener {
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.setClass(InitActivity.this, TLoginActivity.class);
startActivity(intent);
}
}
private class JumpStudent implements View.OnClickListener {
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.setClass(InitActivity.this, SLoginActivity.class);
startActivity(intent);
}
}
private class JumpAdmin implements View.OnClickListener {
@Override
public void onClick(View view) {
customClick(view); //調用自定義的Dialog
}
}
如上,對於角色的選擇其實監聽的是Relative,這樣的話用戶點到圖片、文字或者是外面的邊框都能很好的監聽到實現跳轉,下面是這個頁面中間部分的xml代碼,因爲調試時發現在一些手機屏幕較短的手機上不能很好地適應,所以我加上了ScrollView讓其可上下滑動,增強不同機型的適配效果:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="90dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--選擇了教師-->
<RelativeLayout
android:id="@+id/ChooseTeacher"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:layout_marginRight="45dp"
android:layout_toLeftOf="@+id/canzhao"
android:background="@drawable/translucent2">
<ImageView
android:id="@+id/teacher_ico"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:src="@mipmap/teacher_ico" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/teacher_ico"
android:layout_centerHorizontal="true"
android:layout_marginTop="5dp"
android:text="我是教師"
android:textColor="#576B95"
android:textSize="18sp"
android:textStyle="bold" />
</RelativeLayout>
<!--用作左右兩個選擇的參照物,保證對稱性-->
<TextView
android:id="@+id/canzhao"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true" />
<!--選擇了學生-->
<RelativeLayout
android:id="@+id/ChooseStudent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="45dp"
android:layout_marginTop="50dp"
android:layout_toRightOf="@+id/canzhao"
android:background="@drawable/translucent2">
<ImageView
android:id="@+id/student_ico"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:src="@mipmap/student_ico" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/student_ico"
android:layout_centerHorizontal="true"
android:layout_marginTop="5dp"
android:text="我是學生"
android:textColor="#576B95"
android:textSize="18sp"
android:textStyle="bold" />
</RelativeLayout>
<!--選擇了管理員-->
<RelativeLayout
android:id="@+id/ChooseAdmin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/ChooseStudent"
android:layout_centerHorizontal="true"
android:layout_marginTop="25dp"
android:background="@drawable/translucent2">
<ImageView
android:id="@+id/admin_ico"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:src="@drawable/vector_drawable_admin" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:layout_toEndOf="@id/admin_ico"
android:layout_toRightOf="@id/admin_ico"
android:text="管理員"
android:textColor="#576B95"
android:textSize="16sp"
android:textStyle="bold" />
</RelativeLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="300dp"
android:layout_marginBottom="40dp"
android:background="@drawable/translucent2"
android:lineSpacingExtra="4sp"
android:text="Copyright © 2020 Henry. All Rights Reserved"
android:textAlignment="center"
android:textSize="12sp"
android:textStyle="bold" />
</RelativeLayout>
</ScrollView>
<!--底部的圖片-->
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:adjustViewBounds="true"
android:src="@mipmap/welcomebottom"></ImageView>
</RelativeLayout>
顏色有些刺眼嘻嘻,這裏運用相對佈局包起來的原因是想讓底部的圖片位置固定,不隨屏幕上下移動,一定程度上增加舒適度。
— — — — — — — — — — — — — — — — — — — — — —
② 登錄頁面
我這裏就以學生端登錄頁面做介紹啦:
對於頁面中的【學生登錄】、【註冊】、【登錄】我都修改了其字體,在項目中加上assets文件夾,子目錄創建了fonts文件夾(名字隨意),然後把下載到本地的字體TTF文件複製過來
修改的方式及代碼如下:
btn_Login2 = findViewById(R.id.login2); //獲取登錄按鈕
btn_forget2 = findViewById(R.id.forget2); //獲取忘記密碼
tv_student = findViewById(R.id.tv_student); //獲取學生登錄的TextView
//修改以下三個組件的字體
Typeface customFont = Typeface.createFromAsset(this.getAssets(), "fonts/Coca-Cola.TTF");
tv_student.setTypeface(customFont);
btn_Save2.setTypeface(customFont);
btn_Login2.setTypeface(customFont);
登錄頁面的輸入框中有對於輸入的內容長度的監聽和限制,賬號我設置的是最多10位,密碼最多16位,這裏的位數是和註冊是緊密相關的,監聽以及限制的方法如下:
/**
* 監聽賬號輸入框的文字
**/
private void nameCntentListener() {
usernameEditText2.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Editable editable = usernameEditText2.getText();
int len = editable.length();//輸入文本的長度
if (len > 10) {
int selEndIndex = Selection.getSelectionEnd(editable);
String str = editable.toString();
//截取新字符串
String newStr = str.substring(0, 10);
usernameEditText2.setText(newStr);
editable = usernameEditText2.getText();
//新字符串長度
int newLen = editable.length();
//舊光標位置超過新字符串長度
if (selEndIndex > newLen) {
selEndIndex = editable.length();
}
//設置新光標的位置
Selection.setSelection(editable, selEndIndex);
if (counter1 < 3) { //事不過三哈哈哈
Toast.makeText(SLoginActivity.this, "賬號最多10位吖!", Toast.LENGTH_SHORT).show();
counter1++;
}
}
}
@Override
public void afterTextChanged(Editable editable) {
}
});
}
/**
* 監聽密碼輸入框的文字
**/
private void passwordCntentListener() {
passwordEditText2.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Editable editable = passwordEditText2.getText();
int len = editable.length();//輸入文本的長度
if (len > 16) {
int selEndIndex = Selection.getSelectionEnd(editable);
String str = editable.toString();
String newStr = str.substring(0, 16);
passwordEditText2.setText(newStr);
editable = passwordEditText2.getText();
int newLen = editable.length();
if (selEndIndex > newLen) {
selEndIndex = editable.length();
}
Selection.setSelection(editable, selEndIndex);
if (counter2 < 3) { //事不過三哈哈哈
Toast.makeText(SLoginActivity.this, "密碼最多16位吖!", Toast.LENGTH_SHORT).show();
counter2++;
}
}
}
@Override
public void afterTextChanged(Editable editable) {
}
});
}
對了,這裏如果觸犯了“底線”,輸入超過限制將會彈窗提示,但是不是一直彈的(這樣不太友好),我就設置了最多三次,當然,如果重新進入該頁面的話這個次數是會刷新的~
除去這裏提到的對於輸入框內容的監聽,該Activity的其餘部分的java代碼如下:
public class SLoginActivity extends AppCompatActivity {
private EditText usernameEditText2, passwordEditText2;
private Button btn_Save2, btn_Login2;
private TextView tv_student, btn_forget2;
private int counter1 = 0, counter2 = 0; //限制彈窗的次數,防止用戶一直不符合規則,彈窗彈個不停
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_slogin);
usernameEditText2 = findViewById(R.id.login_username2); //獲取添加用戶名的編輯框
passwordEditText2 = findViewById(R.id.login_password2); //獲取添加密碼的編輯框
btn_Save2 = findViewById(R.id.register2); //獲取註冊按鈕
btn_Login2 = findViewById(R.id.login2); //獲取登錄按鈕
btn_forget2 = findViewById(R.id.forget2); //獲取忘記密碼
tv_student = findViewById(R.id.tv_student); //獲取學生登錄的TextView
//修改以下三個組件的字體
Typeface customFont = Typeface.createFromAsset(this.getAssets(), "fonts/Coca-Cola.TTF");
tv_student.setTypeface(customFont);
btn_Save2.setTypeface(customFont);
btn_Login2.setTypeface(customFont);
nameCntentListener();
passwordCntentListener();
//登錄
btn_Login2.setOnClickListener(new View.OnClickListener() { //單擊登錄按鈕查看是否有該用戶以及密碼是否正確
@Override
public void onClick(View v) {
String student = usernameEditText2.getText().toString().trim();//獲取輸入的登錄名
StudentBean studentBean = null;
//實例化DBUtils,同時調用其方法獲取個人信息資料
studentBean = getStudentData(student);
if (studentBean == null) {
Toast.makeText(SLoginActivity.this, "該賬號不存在,請重新輸入或註冊!", Toast.LENGTH_SHORT).show();
} else {
String passwordIn = passwordEditText2.getText().toString().trim(); //獲取輸入的密碼
nameCntentListener();
passwordCntentListener();
if (studentBean.password.equals(MD5Utils.md5(passwordIn))) { //只是比較內容,不能用==
Toast.makeText(SLoginActivity.this, "登錄成功!" + student + ",歡迎您~", Toast.LENGTH_SHORT).show();
CurrentUser.setUserID(studentBean.ID);//將登錄成功的當前登錄用戶的ID、賬號、姓名和暱稱存爲全局變量
CurrentUser.setUserName(student);
CurrentUser.setRealName(studentBean.realName);
CurrentUser.setNickName(studentBean.nickName);
Intent intent = new Intent(SLoginActivity.this, SMainActivity.class); //登錄成功跳轉學生主界面
startActivity(intent);
finish();
} else {
if (passwordIn.equals("")) {
Toast.makeText(SLoginActivity.this, "密碼不能爲空哦!", Toast.LENGTH_SHORT).show();
} else {
android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(SLoginActivity.this);
final android.app.AlertDialog dialog = builder.create();
final View dialogView = View.inflate(SLoginActivity.this, R.layout.dialog_forget, null);
//設置對話框佈局
dialog.setView(dialogView);
dialog.show();
dialog.getWindow().setBackgroundDrawable(null);
final Button btnCancel = (Button) dialogView.findViewById(R.id.btn_Login_cancel);
final Button btnForget = (Button) dialogView.findViewById(R.id.btn_Login_forget);
btnForget.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
Intent intent = new Intent(SLoginActivity.this, SForgetActivity.class); //跳轉至忘記密碼界面
startActivity(intent);
finish();
}
});
btnCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(SLoginActivity.this, "您選擇了重新輸入,輸入要細心哈", Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
});
}
}
}
}
});
//註冊
btn_Save2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(SLoginActivity.this, SRegisterActivity.class); //跳轉至註冊頁面
startActivity(intent);
finish();
}
});
//忘記密碼
btn_forget2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(SLoginActivity.this, SForgetActivity.class); //跳轉至學生端忘記密碼頁面
startActivity(intent);
finish();
}
});
}
private StudentBean getStudentData(String key) {
StudentBean bean = DBUtils.getInstance(this).getStudentInfo(key);
return bean;
}
}
最後的方法是用來和我定義的操縱數據庫的工具類DBUtils裏的相應方法聯繫起來的,詳細的方法內容會在下面的數據庫部分展示~
— — — — — — — — — — — — — — — — — — — — — —
③ 註冊頁面:
教師端和學生端的註冊頁面有所區別,教師通過手機號註冊(發送短信驗證碼)、學生通過學號註冊:
同樣的,爲了很好地適應不同的手機,我給該頁面也加上了ScrollView:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="90dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--輸入學號-->
<EditText
android:id="@+id/editStudentNum"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="80dp"
android:drawableLeft="@drawable/user_name_icon"
android:drawablePadding="3dp"
android:ems="12"
android:hint=" 輸入您的學號"
android:inputType="number"
android:textColor="#060A00" />
<!--輸入註冊賬號-->
<EditText
android:id="@+id/add_username2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="35dp"
android:ems="12"
android:hint="請輸入賬號"
android:inputType="text"
android:textColor="#060A00" />
<!--輸入密碼-->
<EditText
android:id="@+id/add_password2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
android:ems="12"
android:hint="請輸入密碼"
android:inputType="textPassword" />
<!--確認密碼-->
<EditText
android:id="@+id/confirm_password2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
android:ems="12"
android:hint="請確認密碼"
android:inputType="textPassword"
android:maxLength="16" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="45dp"
android:layout_marginTop="15dp"
android:layout_marginRight="45dp"
android:background="@drawable/translucent4"
android:lineSpacingExtra="2sp"
android:text="① 學號是管理員添加的,若無學號請先登錄管理員身份添加學號\n② 賬號僅允許字母和數字以及-的組合且不超過10位;密碼不能超過16位"
android:textSize="14sp"
android:textStyle="bold" />
<Button
android:id="@+id/buttonRegister2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
android:layout_marginBottom="40dp"
android:text="註冊"
android:textColor="#FF5722"
android:textSize="16sp" />
</LinearLayout>
</ScrollView>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:adjustViewBounds="true"
android:src="@mipmap/welcomebottom" />
</RelativeLayout>
填寫的手機號和學號是通過管理員添加用戶的時候同時添加的,所以,這裏會對填寫的內容進行到數據庫中查詢並對比,沒有的話會彈窗提醒用戶先從管理員端綁定,這裏以學生註冊的功能爲例展示java代碼:
public class SRegisterActivity extends AppCompatActivity {
private Button buttonRegister;
private EditText editTextStudentNum, editTextUserName2, editTextPassword2, editConfirmPassword2;
private String studentNum, userName2, password2, confirm2;
private int counter1 = 0, counter2 = 0; //限制彈窗的次數,防止用戶一直不符合規則,彈窗彈個不停
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sregister);
buttonRegister = findViewById(R.id.buttonRegister2);
editTextStudentNum = findViewById(R.id.editStudentNum);
editTextUserName2 = findViewById(R.id.add_username2);
editTextPassword2 = findViewById(R.id.add_password2);
editConfirmPassword2 = findViewById(R.id.confirm_password2);
//修改註冊按鈕的字體
Typeface customFont = Typeface.createFromAsset(this.getAssets(), "fonts/Coca-Cola.TTF");
buttonRegister.setTypeface(customFont);
nameCntentListener();
passwordCntentListener();
/**
* 註冊
**/
buttonRegister.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
studentNum = editTextStudentNum.getText().toString().trim();
userName2 = editTextUserName2.getText().toString().trim();
password2 = editTextPassword2.getText().toString().trim();
confirm2 = editConfirmPassword2.getText().toString().trim();
StudentBean bean = null;
//檢查數據庫中是否有該學號
bean = getStudentDataByStudentNum(studentNum);
if (bean == null) {
Toast.makeText(SRegisterActivity.this, "該學號不存在,請填寫正確的學號!", Toast.LENGTH_SHORT).show();
} else {
if (bean.userName.equals("暫無")) {
if (userName2.equals("") || password2.equals("")) { //如果填寫的用戶名或密碼爲空時
Toast.makeText(SRegisterActivity.this, "賬號或密碼爲空,請重新填寫", Toast.LENGTH_SHORT).show();
} else {
if (!LimitName.limitName(userName2)) {
Toast.makeText(SRegisterActivity.this, "賬號僅允許英文字母、數字和-的組合", Toast.LENGTH_SHORT).show();
} else {
nameCntentListener();
passwordCntentListener();
if (!password2.equals(confirm2)) { //兩次輸入的密碼不一致
Toast.makeText(SRegisterActivity.this, "兩次輸入的密碼不一致,請重新輸入", Toast.LENGTH_SHORT).show();
editConfirmPassword2.setText(""); //將輸入框內容清除
editTextPassword2.setText("");
} else {
bean.userName = userName2;
bean.nickName = "快給自己起個暱稱叭";
bean.sex = "保密";
bean.qq = "暫無";
bean.wechat = "暫無";
bean.motto = "有點懶吖,啥都沒寫~";
bean.password = MD5Utils.md5(password2);
//保存到ID對應的表中
insertStudent(studentNum, bean);
Toast.makeText(SRegisterActivity.this, "註冊成功!", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(SRegisterActivity.this, SLoginActivity.class);
startActivity(intent);
finish(); //銷燬本Activity
}
}
}
} else {
Toast.makeText(SRegisterActivity.this, "該學號已綁定過用戶!", Toast.LENGTH_SHORT).show();
editTextPassword2.setText(""); //將輸入框內容清除
editConfirmPassword2.setText("");
}
}
}
});
}
private void insertStudent(String id, StudentBean bean) {
DBUtils.getInstance(this).updateStudentInfoAll(id, bean);
}
private StudentBean getStudentDataByStudentNum(String id) {
StudentBean bean = DBUtils.getInstance(this).getStudentInfoByID(id);
return bean;
}
這裏的 nameCntentListener();
和passwordCntentListener();
方法同剛剛的展示的登錄頁面時的方法,稍做修改即可,比較佔屏幕,這裏就不展示了~
對了,這裏關於教師註冊時的手機號發送驗證碼和判斷的部分我也做一個展示吧:
eh = new EventHandler() {
@Override
public void afterEvent(int event, int result, Object data) {
if (result == SMSSDK.RESULT_COMPLETE) {
//回調完成
if (event == SMSSDK.EVENT_SUBMIT_VERIFICATION_CODE) {
//提交驗證碼成功
runOnUiThread(new Runnable() {
@Override
public void run() {
userName = editTextUserName.getText().toString().trim();
password = editTextPassword.getText().toString().trim();
phoneNum = editTextPhoneNum.getText().toString().trim();
confirm = editConfirmPassword.getText().toString().trim();
//如果填寫的用戶名或密碼爲空時
if (userName.equals("") || password.equals("")) {
Toast.makeText(TRegisterActivity.this, "賬號或密碼爲空,請重新填寫", Toast.LENGTH_SHORT).show();
} else {
if (!LimitName.limitName(userName)) {
Toast.makeText(TRegisterActivity.this, "賬號僅允許英文字母、數字和-的組合", Toast.LENGTH_SHORT).show();
} else {
nameCntentListener();
passwordCntentListener();
if (!password.equals(confirm)) { //兩次輸入的密碼不一致
Toast.makeText(TRegisterActivity.this, "兩次輸入的密碼不一致,請重新輸入", Toast.LENGTH_SHORT).show();
editConfirmPassword.setText(""); //將輸入框內容清除
editTextPassword.setText("");
} else {
TeacherBean bean = null;
TeacherBean teacherBean = null;
bean = getTeacherData(userName);
if (bean != null) { //說明就不是暫無了
Toast.makeText(TRegisterActivity.this, "該用戶已存在!", Toast.LENGTH_SHORT).show();
editTextUserName.setText(""); //將輸入框內容清除
editTextPassword.setText("");
editConfirmPassword.setText("");
editTextCode.setText("");
} else {
teacherBean = getTeacherDataByPhoneNum(phoneNum); //因爲還未綁定用戶名,所以只能用手機號獲取到ID綁定用戶
teacherBean.userName = userName;
teacherBean.nickName = "快給自己起個暱稱叭";
teacherBean.sex = "待定";
teacherBean.qq = "待定";
teacherBean.wechat = "待定";
teacherBean.motto = "有點懶吖,啥都沒寫~";
teacherBean.password = MD5Utils.md5(password);
//保存到數據庫
insertTeacher(teacherBean.ID, teacherBean);
Toast.makeText(TRegisterActivity.this, "註冊成功!", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(TRegisterActivity.this, TLoginActivity.class);
startActivity(intent);
finish(); //銷燬本Activity
}
}
}
}
}
});
} else if (event == SMSSDK.EVENT_GET_VOICE_VERIFICATION_CODE) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(TRegisterActivity.this, "語音驗證發送", Toast.LENGTH_SHORT).show();
}
});
} else if (event == SMSSDK.EVENT_GET_VERIFICATION_CODE) {
//獲取驗證碼成功
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(TRegisterActivity.this, "驗證碼已發送", Toast.LENGTH_SHORT).show();
}
});
} else if (event == SMSSDK.EVENT_GET_SUPPORTED_COUNTRIES) {
Log.i("test", "test");
}
} else {
((Throwable) data).printStackTrace();
Throwable throwable = (Throwable) data;
throwable.printStackTrace();
Log.i("1234", throwable.toString());
try {
JSONObject obj = new JSONObject(throwable.getMessage());
final String des = obj.optString("detail");
if (!TextUtils.isEmpty(des)) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(TRegisterActivity.this, des, Toast.LENGTH_SHORT).show();
}
});
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
;
//註冊一個事件回調監聽,用於處理SMSSDK接口請求的結果
SMSSDK.registerEventHandler(eh);
buttonCode.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
phoneNum = editTextPhoneNum.getText().toString();
if (!phoneNum.isEmpty()) {
if (PhoneNumberUtils.checkTel(phoneNum)) { //利用正則表達式檢驗手機號
TeacherBean bean = null;
StudentBean bean2 = null;
//檢查數據庫中該手機號是否已經被綁定
bean = getTeacherDataByPhoneNum(phoneNum);
bean2 = getStudentDataByPhoneNum(phoneNum);
if (bean == null && bean2 == null) {
Toast.makeText(TRegisterActivity.this, "該手機號不可用,需要先以管理員身份添加", Toast.LENGTH_SHORT).show();
} else {
if (bean != null) {
if (!bean.userName.equals("暫無")) {
Toast.makeText(TRegisterActivity.this, "該手機號已綁定過用戶!", Toast.LENGTH_SHORT).show();
} else {
if (bean2 != null) {
if (!bean2.userName.equals("暫無")) {
Toast.makeText(TRegisterActivity.this, "該手機號已綁定過用戶!", Toast.LENGTH_SHORT).show();
} else {
// 獲取驗證碼
SMSSDK.getVerificationCode("86", phoneNum);
}
} else { //bean2 = null, 則肯定未綁定
// 獲取驗證碼
SMSSDK.getVerificationCode("86", phoneNum);
}
}
} else {
if (!bean2.userName.equals("暫無")) {
Toast.makeText(TRegisterActivity.this, "該手機號已綁定過用戶!", Toast.LENGTH_SHORT).show();
} else {
// 獲取驗證碼
SMSSDK.getVerificationCode("86", phoneNum);
}
}
}
} else {
Toast.makeText(getApplicationContext(), "請輸入有效的手機號", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(getApplicationContext(), "請輸入手機號", Toast.LENGTH_SHORT).show();
return;
}
phoneNum = editTextPhoneNum.getText().toString();
}
});
buttonRegister.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
code = editTextCode.getText().toString();
if (!code.isEmpty()) {
//提交驗證碼
SMSSDK.submitVerificationCode("86", phoneNum, code);
} else {
Toast.makeText(getApplicationContext(), "請輸入驗證碼", Toast.LENGTH_SHORT).show();
return;
}
}
});
關於驗證碼平臺的選擇和相關依賴的添加我在之前有介紹過,大家可以直接傳送過去看到:【Android學習之路】之從零開始做一個小項目(一)
— — — — — — — — — — — — — — — — — — — — — —
④ 忘記密碼頁面:
該頁面可從【登錄】頁面直接點擊跳轉或者因爲輸入密碼錯誤彈出我自定義的AlertDialog,如選擇【忘記密碼】則跳轉至該頁面
自定義AlertDialog一會兒會做介紹,這裏的忘記密碼頁面是通過對用戶的手機號發送短信驗證碼進行修改的,所以對於學生用戶來說,需要先綁定手機號(可在登錄後的個人信息頁面綁定,或是在管理員管理學生的頁面綁定),該頁面用到的功能和方法實現與上面的教師註冊頁面很相似的,所以就不展示全部代碼啦,挺多的,感興趣的小夥伴可以直接去看源碼部分~
⑤ 管理員登錄成功的選擇頁面以及管理頁面展示
對用戶的管理頁面,我採用的是ListView
和SimpleCursorAdapter
來實現的實時刷新和顯示,使用這兩個的時候很重要的就是表裏一定要有"_id integer primary key autoincrement"
,不然的話它就會罷工給你看的😅,還有就是需要寫一個用來刷新的方法,我一起在下面做展示吧:
private void initView() {
listView = (ListView) findViewById(R.id.studentListview);
btn_insert = (Button) findViewById(R.id.btn_insert);
btn_search = (Button) findViewById(R.id.btn_search);
et_ID = (EditText) findViewById(R.id.et_studentID);
et_name = (EditText) findViewById(R.id.et_studentName);
et_phone = (EditText) findViewById(R.id.et_studentPhone);
et_search = (EditText) findViewById(R.id.et_searchStudent);
}
private void initEvent() {
btn_insert.setOnClickListener(this);
btn_search.setOnClickListener(this);
openHelper = new DBOpenHelper(this);
mDbWriter = openHelper.getWritableDatabase();
mDbReader = openHelper.getReadableDatabase();
simpleCursorAdapter = new SimpleCursorAdapter(StudentActivity.this, R.layout.user_item, null,
new String[]{"userID", "realName_u", "phoneNumber_u"}, new int[]{R.id.user_id, R.id.user_name, R.id.user_phone}, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
listView.setAdapter(simpleCursorAdapter); //給ListView設置適配器
refreshListview(); //自定義的方法,用於當數據列表改變時刷新ListView
}
//刷新數據列表
public void refreshListview() {
Cursor cursor = mDbWriter.query(DBOpenHelper.USER_INFO, null, "identity=?", new String[]{"1"}, null, null, "userID");
simpleCursorAdapter.changeCursor(cursor);
}
當然啦,如果你想看完整的代碼請前往github看源碼哦~代碼實在太多了,這裏放不下😶
⑥ 登錄後的四個主頁面:
這裏切換的方式使用的是Fragment和BottomNavigationView以及NavController
來實現的,所以需要創建相應的menu目錄和navigation目錄以及相應的xml文件
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tmain);
BottomNavigationView navView2 = findViewById(R.id.nav_view2);
AppBarConfiguration appBarConfiguration2 = new AppBarConfiguration.Builder(
R.id.navigation_tluntan, R.id.navigation_tstudy, R.id.navigation_tplan, R.id.navigation_tme)
.build();
NavController navController2 = Navigation.findNavController(this, R.id.nav_host_fragment2);
NavigationUI.setupActionBarWithNavController(this, navController2, appBarConfiguration2);
NavigationUI.setupWithNavController(navView2, navController2);
}
這個部分主要說一下【個人資料】吧~
其他的部分大家可以戳b站視頻鏈接前往查看~
【個人資料】頁面:
佈局上採用了中間的TextView居中,然後左右的組件向它對齊的方式,這樣能很好的適應不同手機的屏幕,在長度上,我同樣加上了ScrollView,如果屏幕較短可以上下滑動~
佈局文件我只展示其中的一部分,因爲模板是一樣的全貼上太多了:
<!--暱稱-->
<TextView
android:layout_width="wrap_content"
android:layout_height="21dp"
android:layout_marginTop="44dp"
android:layout_marginEnd="3dp"
android:layout_marginRight="3dp"
android:layout_toStartOf="@+id/sInfo_nickname"
android:layout_toLeftOf="@+id/sInfo_nickname"
android:text="暱稱:"
android:textSize="15sp"
android:textStyle="bold" />
<TextView
android:id="@+id/sInfo_nickname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/sInfo_realName"
android:layout_centerHorizontal="true"
android:layout_marginTop="5dp"
android:background="@drawable/translucent8"
android:ems="11"
android:text="啦啦啦"
android:textSize="16sp" />
<ImageButton
android:id="@+id/sEditButton1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="35dp"
android:layout_toRightOf="@+id/sInfo_nickname"
android:background="@drawable/translucent2"
android:src="@mipmap/edit"
android:layout_marginStart="10dp"
android:layout_toEndOf="@+id/sInfo_nickname" />
功能上,給每個右邊的ImageButton加了監聽,如下:
//設置監聽
ib_nickName.setOnClickListener(new EditNickName()); //暱稱編輯
ib_sex.setOnClickListener(new EditSex()); //性別編輯
ib_class.setOnClickListener(new EditClass()); //班級編輯
ib_qq.setOnClickListener(new EditQQ()); //qq編輯
ib_wechat.setOnClickListener(new EditWechat()); //微信編輯
ib_phoneNumber.setOnClickListener(new EditPhoneNumber()); //手機號編輯
ib_motto.setOnClickListener(new EditMotto()); //簽名編輯
方法就展示暱稱的吧~
private class EditNickName implements View.OnClickListener {
@Override
public void onClick(View view) {
android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(SInfoActivity.this);
final android.app.AlertDialog dialog = builder.create();
final View dialogView = View.inflate(SInfoActivity.this, R.layout.dialog_et0_layout, null);
//設置對話框佈局
dialog.setView(dialogView);
dialog.show();
dialog.getWindow().setBackgroundDrawable(null);
final Button btnCommit = (Button) dialogView.findViewById(R.id.btn_info_commit);
final Button btnCancel = (Button) dialogView.findViewById(R.id.btn_info_cancel);
btnCommit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
et_content = (EditText) dialogView.findViewById(R.id.et_myInfo);
String content = et_content.getText().toString().trim();
if (content.equals("")) {
Toast.makeText(SInfoActivity.this, "信息不能爲空呀,請重新填寫", Toast.LENGTH_SHORT).show();
} else {
updateStudent("nickName_s", et_content.getText().toString().trim(), CurrentUser.getuserID());
CurrentUser.setNickName(content); //更新全局變量
Toast.makeText(SInfoActivity.this, "修改成功!", Toast.LENGTH_SHORT).show();
dialog.dismiss();
tv_nickName.setText(content);
}
}
});
btnCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});
}
}
自定義的AlertDialog部分
① 首先是初始頁面的點擊【管理員】後彈出的AlertDialog,如下所示:
/**
* 自定義登錄對話框
*/
private void customClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(InitActivity.this);
final AlertDialog dialog = builder.create();
final View dialogView = View.inflate(InitActivity.this, R.layout.dialog_admin_login, null);
//設置對話框佈局
dialog.setView(dialogView);
dialog.show();
dialog.getWindow().setBackgroundDrawable(null);
final Button btnLogin = (Button) dialogView.findViewById(R.id.btn_login);
final Button btnCancel = (Button) dialogView.findViewById(R.id.btn_cancel);
btnLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
et_name = (EditText) dialogView.findViewById(R.id.et_name);
et_pwd = (EditText) dialogView.findViewById(R.id.et_pwd);
String name = et_name.getText().toString().trim();
String pwd = et_pwd.getText().toString().trim();
if (name.equals("") || pwd.equals("")) {
Toast.makeText(InitActivity.this, "賬號和密碼都不能爲空呀,請重新填寫", Toast.LENGTH_SHORT).show();
} else {
if (name.equals("Henry")) {
if (pwd.equals("666666")) {
Intent intent = new Intent();
intent.setClass(InitActivity.this, AdminActivity.class);
startActivity(intent);
dialog.dismiss();
} else {
Toast.makeText(InitActivity.this, "密碼不正確,請重新填寫", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(InitActivity.this, "賬號不正確,請重新填寫", Toast.LENGTH_SHORT).show();
}
}
}
});
btnCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});
}
樣式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:gravity="center"
android:orientation="vertical">
<LinearLayout
android:layout_width="280dp"
android:layout_height="wrap_content"
android:background="@drawable/custom_dialog_title"
android:gravity="center"
android:minWidth="210dp"
android:orientation="horizontal">
<ImageView
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_marginRight="5dp"
android:src="@drawable/vector_drawable_yz"
android:layout_marginEnd="5dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="50dp"
android:gravity="center"
android:text="管理員驗證"
android:textColor="#fff"
android:textSize="20sp" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/custom_dialog_content"
android:orientation="vertical">
<EditText
android:id="@+id/et_name"
android:layout_width="280dp"
android:layout_height="wrap_content"
android:padding="15dp"
android:hint="請輸入您的賬戶"
android:textSize="18sp" />
<EditText
android:id="@+id/et_pwd"
android:layout_width="280dp"
android:layout_height="wrap_content"
android:padding="15dp"
android:hint="請輸入您的密碼"
android:inputType="numberPassword"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:layout_width="280dp"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:background="@drawable/custom_dialog_bottom"
android:minWidth="210dp"
android:orientation="horizontal"
android:padding="12dp">
<Button
android:id="@+id/btn_cancel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="3dp"
android:layout_marginLeft="3dp"
android:layout_marginEnd="10dp"
android:layout_marginRight="10dp"
android:layout_weight="1"
android:background="@drawable/custom_dialog_negative"
android:text="取消"
android:textColor="@android:color/white"
android:textSize="16sp" />
<Button
android:id="@+id/btn_login"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="3dp"
android:layout_marginRight="3dp"
android:layout_weight="1"
android:background="@drawable/custom_dialog_positive"
android:text="登錄"
android:textColor="@android:color/white"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>
當然按鈕的樣式我也進行相應的修改,默認的樣式確實在這裏不太搭,登錄按鈕的背景樣式如下,分成點擊和未點擊,這樣在點擊後會比較明顯地看出來點擊的效果~
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape>
<solid android:color="#009688"/>
<corners android:radius="6dp"/>
</shape>
</item>
<item android:state_pressed="false">
<shape>
<solid android:color="#009688"/>
<stroke android:width="1dp" android:color="#fff"/>
<corners android:radius="6dp"/>
</shape>
</item>
</selector>
② 各個不需要輸入的AlertDialog:
其實這幾個AlertDialog就是大同小異,框架是一樣的,就是改一改相應的內容和樣式就行啦~
這裏以【身份選擇】爲例展示:
/**
* 自定義選擇對話框
*/
private void selectClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(AdminActivity.this);
final AlertDialog dialog = builder.create();
final View dialogView = View.inflate(AdminActivity.this, R.layout.dialog_admin_teacher, null);
//設置對話框佈局
dialog.setView(dialogView);
dialog.show();
dialog.getWindow().setBackgroundDrawable(null);
final Button btnHead = (Button) dialogView.findViewById(R.id.btn_selectHead);
final Button btnTeacher = (Button) dialogView.findViewById(R.id.btn_selectTeacher);
btnHead.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setClass(AdminActivity.this, TeacherActivity.class);
startActivity(intent);
dialog.dismiss();
}
});
btnTeacher.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setClass(AdminActivity.this, Teacher2Activity.class);
startActivity(intent);
dialog.dismiss();
}
});
}
還有與之對應的讓它看起來好看一些的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:gravity="center"
android:orientation="vertical">
<LinearLayout
android:layout_width="280dp"
android:layout_height="wrap_content"
android:background="@drawable/custom_dialog_title"
android:gravity="center"
android:minWidth="210dp"
android:orientation="horizontal">
<ImageView
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:src="@drawable/vector_drawable_identity" />
<TextView
android:layout_width="wrap_content"
android:layout_height="50dp"
android:gravity="center"
android:text="身份選擇"
android:textColor="#fff"
android:textSize="20sp" />
</LinearLayout>
<LinearLayout
android:layout_width="280dp"
android:layout_height="wrap_content"
android:background="@drawable/custom_dialog_content"
android:gravity="center"
android:minWidth="210dp"
android:minHeight="80dp"
android:orientation="vertical">
<TextView
android:layout_width="280dp"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="請選擇您的身份"
android:textAlignment="center"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:layout_width="280dp"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:background="@drawable/custom_dialog_bottom"
android:minWidth="210dp"
android:orientation="horizontal"
android:padding="12dp">
<Button
android:id="@+id/btn_selectHead"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="3dp"
android:layout_marginLeft="3dp"
android:layout_marginEnd="10dp"
android:layout_marginRight="10dp"
android:layout_weight="1"
android:background="@drawable/custom_dialog_negative"
android:text="班主任"
android:textColor="@android:color/white"
android:textSize="16sp" />
<Button
android:id="@+id/btn_selectTeacher"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="3dp"
android:layout_marginRight="3dp"
android:layout_weight="1"
android:background="@drawable/custom_dialog_positive"
android:text="任課老師"
android:textColor="@android:color/white"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>
總結起來的話其實就是相當於像寫一個界面的佈局一樣地來設計這個Dialog,不過它的大小比較小而已,而且要注意它的內容、組件和AlertDialog的匹配,不能自己想設計成什麼樣就設計成什麼樣,要按照AlertDialog的方法來的~
數據庫部分
該部分我相信大家如果看過我之前記錄過程的博客就能知道我使用SQLite數據庫的方法啦😁
① 首先是繼承自SQLiteOpenHelpe
的DBOpenHelper
類:
package com.henry.myschoolsystem.ui.login;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DBOpenHelper extends SQLiteOpenHelper {
public static final String TEACHER_INFO = "teacherInfo";
public static final String STUDENT_INFO = "studentInfo";
public static final String CLASS = "class";
public static final String COURSE = "course";
public static final String SPLAN = "studentPlan";
public static final String SPLANFINISHED = "studentPlanFinished";
public static final String TPLAN = "teacherPlan";
public static final String TPLANFINISHED = "teacherPlanFinished";
public static final String USER_INFO = "userInfo";
public static final String LOG = "userLog";
// public DBOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
// super(context, name, null, version); //重寫構造方法並設置factory爲null
// }
public DBOpenHelper(Context context){
super(context, "mySchool0030.db", null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
/**
* 當該子類被實例化時會創建指定名的數據庫,在onCreate中按以下的SQL語句創建相應的表
**/
db.execSQL("CREATE TABLE IF NOT EXISTS " + USER_INFO + "( "
+ "_id integer primary key autoincrement, "
+ "userID TEXT UNIQUE NOT NULL, "
+ "realName_u TEXT NOT NULL, " //真實姓名(教師或學生)
+ "phoneNumber_u TEXT, "
+ "identity TEXT NOT NULL," //用來標記該用戶是教師還是學生(0:教師,1:學生)
+ "isHead_u TEXT," //添加的是教師時用來標記是否爲班主任(0:不是,1:是)
+ "classID_u TEXT" //是班主任的話需填寫班級ID
+ ")");
db.execSQL("CREATE TABLE IF NOT EXISTS " + TEACHER_INFO + "( "
+ "teacherID TEXT PRIMARY KEY, "
+ "userName_t TEXT NOT NULL, "
+ "realName_t TEXT NOT NULL, " //真實姓名
+ "nickName_t TEXT, " //暱稱
+ "isHead_t TEXT NOT NULL, " //標記是否爲班主任 (0:不是,1:是)
+ "sex_t TEXT, "
+ "qq_t TEXT, "
+ "wechat_t TEXT, "
+ "motto_t TEXT, "
+ "phoneNumber_t TEXT NOT NULL, "
+ "password_t TEXT NOT NULL"
+ ")");
db.execSQL("CREATE TABLE IF NOT EXISTS " + STUDENT_INFO + "( "
+ "studentID TEXT PRIMARY KEY, "
+ "userName_s TEXT NOT NULL, "
+ "realName_s TEXT NOT NULL, " //真實姓名
+ "nickName_s TEXT, " //暱稱
+ "sex_s TEXT, "
+ "qq_s TEXT, "
+ "wechat_s TEXT, "
+ "motto_s TEXT, "
+ "phoneNumber_s TEXT, "
+ "password_s TEXT NOT NULL"
+ ")");
db.execSQL("CREATE TABLE IF NOT EXISTS " + CLASS + "( "
+ "_id integer primary key autoincrement, "
+ "classID TEXT NOT NULL, "
+ "className TEXT NOT NULL, "
+ "year TEXT NOT NULL, " //年級
+ "studentID_c TEXT, "
+ "teacherID_c TEXT, "
+ "teacherName_c TEXT, " //班主任姓名
+ "code TEXT NOT NULL " //學生加入班級需要的驗證碼
+ ")");
db.execSQL("CREATE TABLE IF NOT EXISTS " + COURSE + "( "
+ "courseID TEXT PRIMARY KEY, "
+ "courseName TEXT NOT NULL, "
+ "studentID TEXT REFERENCES studentInfo(studentID), "
+ "teacherName TEXT REFERENCES teacherInfo(realName_t), " //任課教師姓名
+ "grade TEXT, " //學生所得分數
+ "credit TEXT NOT NULL " //該課程的學分
+ ")");
db.execSQL("CREATE TABLE IF NOT EXISTS " + SPLAN + "( "
+ "_id integer primary key autoincrement, "
+ "planContent_s TEXT, " //計劃的具體內容
+ "studentID_p TEXT, "
+ "deadline_s TEXT" //計劃的最終期限
+ ")");
db.execSQL("CREATE TABLE IF NOT EXISTS " + SPLANFINISHED + "( "
+ "_id integer primary key autoincrement, "
+ "studentID_pf TEXT, "
+ "finishedTime_s TEXT, " //計劃的完成時間
+ "finishedContent_s TEXT " //完成的計劃內容
+ ")");
db.execSQL("CREATE TABLE IF NOT EXISTS " + TPLAN + "( "
+ "_id integer primary key autoincrement, "
+ "planContent_t TEXT, " //計劃的具體內容
+ "TeacherID_p TEXT, "
+ "deadline_t TEXT " //計劃的最終期限
+ ")");
db.execSQL("CREATE TABLE IF NOT EXISTS " + TPLANFINISHED + "( "
+ "_id integer primary key autoincrement, "
+ "teacherID_pf TEXT, "
+ "finishedTime_t TEXT, " //計劃的完成時間
+ "finishedContent_t TEXT " //完成的計劃內容
+ ")");
db.execSQL("CREATE TABLE IF NOT EXISTS " + LOG + "( "
+ "_id integer primary key autoincrement, "
+ "userID_l TEXT NOT NULL, " //登錄的用戶ID
+ "userName_l TEXT NOT NULL, " //登錄的用戶姓名
+ "logContent TEXT NOT NULL " //日誌的具體內容
+ ")");
}
@Override
// 重寫基類的onUpgrade()方法,以便數據庫版本更新
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//提示版本更新並輸出舊版本信息與新版本信息
System.out.println("---版本更新-----" + oldVersion + "--->" + newVersion);
}
}
在該類中重寫構造方法以及建表所需的SQL語句
② 數據庫工具類DBUtils:
package com.henry.myschoolsystem.utils;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import com.henry.myschoolsystem.bean.ClassBean;
import com.henry.myschoolsystem.bean.LogBean;
import com.henry.myschoolsystem.bean.StudentBean;
import com.henry.myschoolsystem.bean.TeacherBean;
import com.henry.myschoolsystem.bean.UserBean;
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;
}
/**
* 給班級添加學生信息(在class表中)
**/
public void saveStudentInfo(ClassBean classBean) {
ContentValues cv = new ContentValues();
cv.put("classID",classBean.classID);
cv.put("className",classBean.className);
cv.put("year",classBean.year);
cv.put("studentID_c",classBean.studentID);
cv.put("teacherID_c",classBean.teacherID);
cv.put("teacherName_c",classBean.teacherName);
cv.put("code",classBean.code);
db.insert(DBOpenHelper.CLASS, null, cv);
}
/**
* 保存日誌信息
**/
public void savaLogInfo(LogBean logBean) {
ContentValues cv = new ContentValues();
cv.put("userID_l",logBean.userID);
cv.put("userName_l",logBean.userName);
cv.put("logContent",logBean.time);
db.insert(DBOpenHelper.LOG, null, cv);
}
// ---------------------------------------------------------------------------------------------
/**
* 通過學號獲取班級信息(學生個人信息頁面用到)
**/
public ClassBean getClassInfoByStudentID(String id) {
String sql = "SELECT * FROM " + DBOpenHelper.CLASS + " WHERE studentID_c=?";
Cursor cursor = db.rawQuery(sql, new String[]{id});
ClassBean classBean = null;
while (cursor.moveToNext()) {
classBean = new ClassBean();
classBean.classID = cursor.getString(cursor.getColumnIndex("classID"));
classBean.className = cursor.getString(cursor.getColumnIndex("className"));
classBean.year = cursor.getString(cursor.getColumnIndex("year"));
classBean.studentID = cursor.getString(cursor.getColumnIndex("studentID_c"));
classBean.teacherID = cursor.getString(cursor.getColumnIndex("teacherID_c"));
classBean.teacherName = cursor.getString(cursor.getColumnIndex("teacherName_c"));
classBean.code = cursor.getString(cursor.getColumnIndex("code"));
}
cursor.close();
return classBean;
}
/**
* 通過工號獲取班級信息(教師個人信息頁面用到)
**/
public ClassBean getClassDataByTeacherID(String id) {
String sql = "SELECT * FROM " + DBOpenHelper.CLASS + " WHERE teacherID_c=?";
Cursor cursor = db.rawQuery(sql, new String[]{id});
ClassBean classBean = null;
while (cursor.moveToNext()) {
classBean = new ClassBean();
classBean.classID = cursor.getString(cursor.getColumnIndex("classID"));
classBean.className = cursor.getString(cursor.getColumnIndex("className"));
classBean.year = cursor.getString(cursor.getColumnIndex("year"));
classBean.studentID = cursor.getString(cursor.getColumnIndex("studentID_c"));
classBean.teacherID = cursor.getString(cursor.getColumnIndex("teacherID_c"));
classBean.teacherName = cursor.getString(cursor.getColumnIndex("teacherName_c"));
classBean.code = cursor.getString(cursor.getColumnIndex("code"));
}
cursor.close();
return classBean;
}
/**
* 通過班級ID獲取班級信息
**/
public ClassBean getClassInfoByID(String id) {
String sql = "SELECT * FROM " + DBOpenHelper.CLASS + " WHERE classID=?";
Cursor cursor = db.rawQuery(sql, new String[]{id});
ClassBean classBean = null;
while (cursor.moveToNext()) {
classBean = new ClassBean();
classBean.classID = cursor.getString(cursor.getColumnIndex("classID"));
classBean.className = cursor.getString(cursor.getColumnIndex("className"));
classBean.year = cursor.getString(cursor.getColumnIndex("year"));
classBean.studentID = cursor.getString(cursor.getColumnIndex("studentID_c"));
classBean.teacherID = cursor.getString(cursor.getColumnIndex("teacherID_c"));
classBean.teacherName = cursor.getString(cursor.getColumnIndex("teacherName_c"));
classBean.code = cursor.getString(cursor.getColumnIndex("code"));
}
cursor.close();
return classBean;
}
/**
* 通過工號獲取教師資料信息
**/
public TeacherBean getTeacherInfoByID(String id) {
String sql = "SELECT * FROM " + DBOpenHelper.TEACHER_INFO + " WHERE teacherID=?";
Cursor cursor = db.rawQuery(sql, new String[]{id});
TeacherBean teacherBean = null;
while (cursor.moveToNext()) {
teacherBean = new TeacherBean();
//將對應用戶名的所有數據從表中動態賦值給bean
teacherBean.userName = cursor.getString(cursor.getColumnIndex("userName_t"));
teacherBean.realName = cursor.getString(cursor.getColumnIndex("realName_t"));
teacherBean.nickName = cursor.getString(cursor.getColumnIndex("nickName_t"));
teacherBean.ID = cursor.getString(cursor.getColumnIndex("teacherID"));
teacherBean.sex = cursor.getString(cursor.getColumnIndex("sex_t"));
teacherBean.qq = cursor.getString(cursor.getColumnIndex("qq_t"));
teacherBean.wechat = cursor.getString(cursor.getColumnIndex("wechat_t"));
teacherBean.motto = cursor.getString(cursor.getColumnIndex("motto_t"));
teacherBean.phoneNumber = cursor.getString(cursor.getColumnIndex("phoneNumber_t"));
teacherBean.password = cursor.getString(cursor.getColumnIndex("password_t"));
teacherBean.isHead = cursor.getString(cursor.getColumnIndex("isHead_t"));
}
cursor.close();
return teacherBean;
}
/**
* 通過賬號獲取教師資料信息
**/
public TeacherBean getTeacherInfo(String teacherName) {
String sql = "SELECT * FROM " + DBOpenHelper.TEACHER_INFO + " WHERE userName_t=?";
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_t"));
teacherBean.realName = cursor.getString(cursor.getColumnIndex("realName_t"));
teacherBean.nickName = cursor.getString(cursor.getColumnIndex("nickName_t"));
teacherBean.ID = cursor.getString(cursor.getColumnIndex("teacherID"));
teacherBean.sex = cursor.getString(cursor.getColumnIndex("sex_t"));
teacherBean.qq = cursor.getString(cursor.getColumnIndex("qq_t"));
teacherBean.wechat = cursor.getString(cursor.getColumnIndex("wechat_t"));
teacherBean.motto = cursor.getString(cursor.getColumnIndex("motto_t"));
teacherBean.phoneNumber = cursor.getString(cursor.getColumnIndex("phoneNumber_t"));
teacherBean.password = cursor.getString(cursor.getColumnIndex("password_t"));
teacherBean.isHead = cursor.getString(cursor.getColumnIndex("isHead_t"));
}
cursor.close();
return teacherBean;
}
/**
* 通過手機號獲取教師資料信息
**/
public TeacherBean getTeacherInfoByPhoneNum(String phone) {
String sql = "SELECT * FROM " + DBOpenHelper.TEACHER_INFO + " WHERE phoneNumber_t=?";
Cursor cursor = db.rawQuery(sql, new String[]{phone});
TeacherBean teacherBean = null;
while (cursor.moveToNext()) {
teacherBean = new TeacherBean();
//將對應用戶名的所有數據從表中動態賦值給bean
teacherBean.userName = cursor.getString(cursor.getColumnIndex("userName_t"));
teacherBean.realName = cursor.getString(cursor.getColumnIndex("realName_t"));
teacherBean.nickName = cursor.getString(cursor.getColumnIndex("nickName_t"));
teacherBean.ID = cursor.getString(cursor.getColumnIndex("teacherID"));
teacherBean.sex = cursor.getString(cursor.getColumnIndex("sex_t"));
teacherBean.qq = cursor.getString(cursor.getColumnIndex("qq_t"));
teacherBean.wechat = cursor.getString(cursor.getColumnIndex("wechat_t"));
teacherBean.motto = cursor.getString(cursor.getColumnIndex("motto_t"));
teacherBean.phoneNumber = cursor.getString(cursor.getColumnIndex("phoneNumber_t"));
teacherBean.password = cursor.getString(cursor.getColumnIndex("password_t"));
teacherBean.isHead = cursor.getString(cursor.getColumnIndex("isHead_t"));
}
cursor.close();
return teacherBean;
}
/**
* 通過賬號獲取學生資料信息
**/
public StudentBean getStudentInfo(String studentName) {
String sql = "SELECT * FROM " + DBOpenHelper.STUDENT_INFO + " WHERE userName_s=?";
Cursor cursor = db.rawQuery(sql, new String[]{studentName});
StudentBean studentBean = null;
while (cursor.moveToNext()) {
studentBean = new StudentBean();
//將對應用戶名的所有數據從表中動態賦值給bean
studentBean.userName = cursor.getString(cursor.getColumnIndex("userName_s"));
studentBean.realName = cursor.getString(cursor.getColumnIndex("realName_s"));
studentBean.nickName = cursor.getString(cursor.getColumnIndex("nickName_s"));
studentBean.sex = cursor.getString(cursor.getColumnIndex("sex_s"));
studentBean.qq = cursor.getString(cursor.getColumnIndex("qq_s"));
studentBean.wechat = cursor.getString(cursor.getColumnIndex("wechat_s"));
studentBean.motto = cursor.getString(cursor.getColumnIndex("motto_s"));
studentBean.ID = cursor.getString(cursor.getColumnIndex("studentID"));
studentBean.password = cursor.getString(cursor.getColumnIndex("password_s"));
studentBean.phoneNumber = cursor.getString(cursor.getColumnIndex("phoneNumber_s"));
}
cursor.close();
return studentBean;
}
/**
* 通過學號獲取學生資料信息
**/
public StudentBean getStudentInfoByID(String id) {
String sql = "SELECT * FROM " + DBOpenHelper.STUDENT_INFO + " WHERE studentID=?";
Cursor cursor = db.rawQuery(sql, new String[]{id});
StudentBean studentBean = null;
while (cursor.moveToNext()) {
studentBean = new StudentBean();
//將對應用戶名的所有數據從表中動態賦值給bean
studentBean.userName = cursor.getString(cursor.getColumnIndex("userName_s"));
studentBean.realName = cursor.getString(cursor.getColumnIndex("realName_s"));
studentBean.nickName = cursor.getString(cursor.getColumnIndex("nickName_s"));
studentBean.sex = cursor.getString(cursor.getColumnIndex("sex_s"));
studentBean.qq = cursor.getString(cursor.getColumnIndex("qq_s"));
studentBean.wechat = cursor.getString(cursor.getColumnIndex("wechat_s"));
studentBean.motto = cursor.getString(cursor.getColumnIndex("motto_s"));
studentBean.ID = cursor.getString(cursor.getColumnIndex("studentID"));
studentBean.password = cursor.getString(cursor.getColumnIndex("password_s"));
studentBean.phoneNumber = cursor.getString(cursor.getColumnIndex("phoneNumber_s"));
}
cursor.close();
return studentBean;
}
/**
* 通過手機號獲取學生資料信息
**/
public StudentBean getStudentInfoByPhoneNum(String phone) {
String sql = "SELECT * FROM " + DBOpenHelper.STUDENT_INFO + " WHERE phoneNumber_s=?";
Cursor cursor = db.rawQuery(sql, new String[]{phone});
StudentBean studentBean = null;
while (cursor.moveToNext()) {
studentBean = new StudentBean();
//將對應用戶名的所有數據從表中動態賦值給bean
studentBean.userName = cursor.getString(cursor.getColumnIndex("userName_s"));
studentBean.realName = cursor.getString(cursor.getColumnIndex("realName_s"));
studentBean.nickName = cursor.getString(cursor.getColumnIndex("nickName_s"));
studentBean.sex = cursor.getString(cursor.getColumnIndex("sex_s"));
studentBean.qq = cursor.getString(cursor.getColumnIndex("qq_s"));
studentBean.wechat = cursor.getString(cursor.getColumnIndex("wechat_s"));
studentBean.motto = cursor.getString(cursor.getColumnIndex("motto_s"));
studentBean.ID = cursor.getString(cursor.getColumnIndex("studentID"));
studentBean.password = cursor.getString(cursor.getColumnIndex("password_s"));
studentBean.phoneNumber = cursor.getString(cursor.getColumnIndex("phoneNumber_s"));
}
cursor.close();
return studentBean;
}
// ---------------------------------------------------------------------------------------------
/**
* 通過ID獲取管理員資料信息
**/
public UserBean getUserInfoByID(String id) {
String sql = "SELECT * FROM " + DBOpenHelper.USER_INFO + " WHERE userID=?";
Cursor cursor = db.rawQuery(sql, new String[]{id});
UserBean userBean = null;
while (cursor.moveToNext()) {
userBean = new UserBean();
//將對應用戶名的所有數據從表中動態賦值給bean
userBean.ID = cursor.getString(cursor.getColumnIndex("userID"));
userBean.realName = cursor.getString(cursor.getColumnIndex("realName_u"));
userBean.phoneNumber = cursor.getString(cursor.getColumnIndex("phoneNumber_u"));
userBean.identity = cursor.getString(cursor.getColumnIndex("identity"));
userBean.isHead = cursor.getString(cursor.getColumnIndex("isHead_u"));
userBean.classID = cursor.getString(cursor.getColumnIndex("classID_u"));
}
cursor.close();
return userBean;
}
/**
* 通過手機號獲取管理員操作的資料信息
**/
public UserBean getUserInfoByPhoneNum(String phone) {
String sql = "SELECT * FROM " + DBOpenHelper.USER_INFO + " WHERE phoneNumber_u=?";
Cursor cursor = db.rawQuery(sql, new String[]{phone});
UserBean userBean = null;
while (cursor.moveToNext()) {
userBean = new UserBean();
//將對應用戶名的所有數據從表中動態賦值給bean
userBean.ID = cursor.getString(cursor.getColumnIndex("userID"));
userBean.realName = cursor.getString(cursor.getColumnIndex("realName_u"));
userBean.phoneNumber = cursor.getString(cursor.getColumnIndex("phoneNumber_u"));
userBean.identity = cursor.getString(cursor.getColumnIndex("identity"));
userBean.isHead = cursor.getString(cursor.getColumnIndex("isHead_u"));
userBean.classID = cursor.getString(cursor.getColumnIndex("classID_u"));
}
cursor.close();
return userBean;
}
// ---------------------------------------------------------------------------------------------
/**
* 根據用戶名修改教師資料信息,這裏的key指代表字段,value表示數值
**/
public void updateTeacherInfo(String key, String value, String userName) {
ContentValues cv = new ContentValues();
cv.put(key, value);
db.update(DBOpenHelper.TEACHER_INFO, cv, "userName_t=?", new String[]{userName});
}
/**
* 根據手機號修改教師資料信息,這裏的key指代表字段,value表示數值
**/
public void updateTeacherInfoByPhone(String key, String value, String phone) {
ContentValues cv = new ContentValues();
cv.put(key, value);
db.update(DBOpenHelper.TEACHER_INFO, cv, "phoneNumber_t=?", new String[]{phone});
}
/**
* 根據ID修改學生資料信息,這裏的key指代表字段,value表示數值
**/
public void updateStudentInfoByID(String key, String value, String id) {
ContentValues cv = new ContentValues();
cv.put(key, value);
db.update(DBOpenHelper.STUDENT_INFO, cv, "studentID=?", new String[]{id});
}
/**
* 根據手機號修改學生資料信息,這裏的key指代表字段,value表示數值
**/
public void updateStudentInfoByPhone(String key, String value, String phone) {
ContentValues cv = new ContentValues();
cv.put(key, value);
db.update(DBOpenHelper.STUDENT_INFO, cv, "phoneNumber_s=?", new String[]{phone});
}
// --------------------------------!!!很重要!!!------------------------------------------------
/**
* 註冊時的整體修改教師資料信息
**/
public void updateTeacherInfoAll(String id, TeacherBean teacherBean) {
ContentValues cv = new ContentValues();
cv.put("userName_t", teacherBean.userName);
cv.put("nickName_t", teacherBean.nickName);
cv.put("sex_t", teacherBean.sex);
cv.put("qq_t", teacherBean.qq);
cv.put("wechat_t",teacherBean.wechat);
cv.put("motto_t",teacherBean.motto);
cv.put("password_t",teacherBean.password);
db.update(DBOpenHelper.TEACHER_INFO, cv, "teacherID=?", new String[]{id});
}
/**
* 註冊時的整體修改學生資料信息
**/
public void updateStudentInfoAll(String id, StudentBean studentBean) {
ContentValues cv = new ContentValues();
cv.put("userName_s", studentBean.userName);
cv.put("nickName_s", studentBean.nickName);
cv.put("sex_s", studentBean.sex);
cv.put("qq_s", studentBean.qq);
cv.put("wechat_s",studentBean.wechat);
cv.put("motto_s",studentBean.motto);
cv.put("password_s",studentBean.password);
db.update(DBOpenHelper.STUDENT_INFO, cv, "studentID=?", new String[]{id});
}
/**
* 註冊時的修改學生與班級的綁定信息
**/
public void updateClassInfoAll(String id, ClassBean classBean) {
ContentValues cv = new ContentValues();
cv.put("classID", classBean.classID);
cv.put("className", classBean.className);
cv.put("year", classBean.year);
cv.put("code", classBean.code);
cv.put("teacherID_c", classBean.teacherID);
cv.put("teacherName_c", classBean.teacherName);
db.update(DBOpenHelper.CLASS, cv, "studentID_c=?", new String[]{id});
}
}
該類是用於將需要用到數據庫的頁面和數據庫聯繫起來的“中介”,寫有很多操縱數據庫以及相關數據的方法,在需要用到的頁面寫上一個調用的方法即可很好地實現😀
③ 同時,不可缺少的是bean文件夾:
這裏展示一下StudentBean:
package com.henry.myschoolsystem.bean;
public class StudentBean {
public String userName; //賬號
public String realName; //真實姓名
public String nickName; //暱稱
public String sex; //性別
public String qq; //QQ號
public String wechat; //微信號
public String motto; //個性簽名
public String ID; //學生學號
public String password; //密碼
public String phoneNumber; //手機號
}
這個使用數據庫的方法是我之前蒐集和查看了很多資料後總結出來,然後結合自身的想法和實踐寫出來的,挺好用的,按目前使用來看,還未出現bug,至於性能方面有待考量(目前能力還不足以在多種方法間挑選出性能最優的,按目前使用情況和效果來看我自己會首選使用該方法😁)
👀本文其實主要是對該項目做一個大致的代碼展示,將同類型的歸結在了一起,代碼中也做了很多的註釋~ 至於具體的一些細節和使用,本文就不涉及啦,在之後會分開寫幾篇總結篇來分享經驗和心得(寫一起實在太多了哈哈),對於文中解釋不清楚的地方或是小夥伴們感興趣的地方歡迎郵箱聯繫我,一起探討學習😊
我的郵箱:[email protected]
B站項目視頻講解傳送:https://www.bilibili.com/video/bv1fD4y1D7P6
github項目源代碼: SchoolSystem