Android 持久化技术

目录

1. 用户登陆界面

2. 图书信息数据库和显示界面

3.应用运行功能的截图

4.源码


1. 用户登陆界面

  ( 1 ) 创建一个 LoginActivity ,对应的布局文件 activity_login
  ( 2 ) 具备两个 TextView 和两个 EditText 控件,分别用于显示和输入用户名和密码。
  ( 3 ) 添加 注册 登陆 两个按钮( Button )。
  ( 4 ) 添加 记住我 功能:插入一个 CheckBox 控件,当用户勾选该勾选框,当点击 登陆
按钮时,判断该勾选框,如果勾选,则把用户名和密码保存起来,要求采用文本存储方式保
存下来。
  ( 5 ) 点击 注册 ,可以根据用户名和密码对应的 EditText ,将用户名和密码保存起来,
要求采用 SharedPreferences 保存用户名和密码数据,同时需要确保用户名不重复(区分
大小写)。
  ( 6 ) 点击 登陆 ,通过 SharedPreferences 读取用户密码数据,并进行匹配,只有匹
配成功,才能成功登陆,跳转到 MainActivity (下一个设计内容)

2. 图书信息数据库和显示界面

1 ) 需要保存的信息:书本信息(下表左),和书本所属类别(下表右)。每本书有其
所属的类别。

create table Book (
id integer primary key autoincrement,
author text,
price real,
pages integer,
name text

category_id integer

)

create table Category (
id integer primary key autoincrement
category_name text,
category_code integer)

使用 SqlLite 数据库创建数据库 library ,并创建 Book Category 这两个表。往
Category 里插入 2 条默认书类别数据(如:经济类, 1 )。
2 ) 界面设计:
        ① 创建一个 MainActivity ,对应的布局为 activity_main
        ② 添加一个 RecyclerView ,用于显示所有的图书条目信息,每个条目显示书的名字、
        作者、类别和价格。
        ③ 添加一个 添加书目 的按钮,用于跳转进入 AddBookActivity
        ④ 在 AddBookActivity 中 , 可 以 添 加 一 本 书 的 信 息 到 数 据 库 中 。 提 示 :
        AddBookActivity 需要的组件包括: EditText TextView Button Spinner
        提醒:可以在 RecyclerView 的适配器里面进行数据库的查询操作。

3.应用运行功能的截图

登录、注册、检查重名、检查账户密码是否正确、密码是否正确、记住密码
登录成功后进入首页面:

4.源码

Book.kt
data class Book(
val author : String ,
val price : Double ,
val pages : Int ,
val name : String ,
val categoryId : Int
)
Category.kt
package com.example.mylibrary
data class Category(
val id : Int ,
val categoryName : String ,
val categoryCode : Int
)
LoginActivity.kt
package com.example.mylibrary
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.CheckBox
import android.widget.EditText
import android.widget.Toast
class LoginActivity : AppCompatActivity() {
private lateinit var usernameEditText : EditText
private lateinit var passwordEditText : EditText
private lateinit var rememberMeCheckBox : CheckBox
private lateinit var sharedPreferences : SharedPreferences
override fun onCreate (savedInstanceState: Bundle?) {
super .onCreate(savedInstanceState)
setContentView(R.layout. activity_login )
usernameEditText = findViewById(R.id. usernameEditText )
passwordEditText = findViewById(R.id. passwordEditText )
rememberMeCheckBox = findViewById(R.id. rememberMeCheckBox )
val loginButton: Button = findViewById(R.id. loginButton )
val registerButton: Button = findViewById(R.id. registerButton )
sharedPreferences = getSharedPreferences( "MyPrefs" ,
Context. MODE_PRIVATE )
loginButton.setOnClickListener {
val username = usernameEditText . text .toString()
val password = passwordEditText . text .toString()
if (validateLogin(username , password)) {
if ( rememberMeCheckBox . isChecked ) {
rememberUser(username , password)
}
val intent = Intent( this @LoginActivity ,
MainActivity:: class . java )
startActivity(intent)
//
finish()
} else {
Toast.makeText( this @LoginActivity , "Invalid username or
password" , Toast. LENGTH_SHORT ).show()
}
}
registerButton.setOnClickListener {
val username = usernameEditText . text .toString()
val password = passwordEditText . text .toString()
if (registerUser(username , password)) {
Toast.makeText( this @LoginActivity , "Registration
successful" , Toast. LENGTH_SHORT ).show()
} else {
Toast.makeText( this @LoginActivity , "Username already
exists" , Toast. LENGTH_SHORT ).show()
}
}
} private fun validateLogin (username: String , password: String): Boolean
{
val storedPassword = sharedPreferences .getString(username , null )
return storedPassword == password
}
private fun rememberUser (username: String , password: String) {
val editor = sharedPreferences .edit()
editor.putString(username , password)
editor.apply()
}
private fun registerUser (username: String , password: String): Boolean {
if (! sharedPreferences .contains(username)) {
val editor = sharedPreferences .edit()
editor.putString(username , password)
editor.apply()
return true
}
return false
}
}
activity_login.xml
<? xml version ="1.0" encoding ="utf-8" ?>
<RelativeLayout
xmlns: android ="http://schemas.android.com/apk/res/android"
android :layout_width ="match_parent"
android :layout_height ="match_parent"
android :padding ="16dp" >
<TextView
android :id ="@+id/usernameTextView"
android :layout_width ="wrap_content"
android :layout_height ="wrap_content"
android :text ="Username"
android :layout_marginBottom ="8dp" />
<EditText
android :id ="@+id/usernameEditText"
android :layout_width ="match_parent"
android :layout_height ="wrap_content"
android :layout_below ="@id/usernameTextView"
android :hint ="Enter username"
android :padding ="12dp"
10 android :layout_marginBottom ="16dp" />
<TextView
android :id ="@+id/passwordTextView"
android :layout_width ="wrap_content"
android :layout_height ="wrap_content"
android :layout_below ="@id/usernameEditText"
android :text ="Password"
android :layout_marginBottom ="8dp" />
<EditText
android :id ="@+id/passwordEditText"
android :layout_width ="match_parent"
android :layout_height ="wrap_content"
android :layout_below ="@id/passwordTextView"
android :inputType ="textPassword"
android :hint ="Enter password"
android :padding ="12dp"
android :layout_marginBottom ="16dp" />
<CheckBox
android :id ="@+id/rememberMeCheckBox"
android :layout_width ="wrap_content"
android :layout_height ="wrap_content"
android :text ="Remember me"
android :layout_below ="@id/passwordEditText"
android :layout_marginBottom ="16dp" />
<Button
android :id ="@+id/loginButton"
android :layout_width ="match_parent"
android :layout_height ="wrap_content"
android :text ="Login"
android :layout_below ="@id/rememberMeCheckBox"
android :layout_marginBottom ="8dp" />
<Button
android :id ="@+id/registerButton"
android :layout_width ="match_parent"
android :layout_height ="wrap_content"
android :text ="Register"
android :layout_below ="@id/loginButton" />
</RelativeLayout>
MainActivity.kt
package com.example.mylibrary
import android.content.Intent
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
class MainActivity : AppCompatActivity() {
private lateinit var recyclerView : RecyclerView
private lateinit var bookAdapter : BookAdapter
private lateinit var emptyView : TextView
override fun onCreate (savedInstanceState: Bundle?) {
super .onCreate(savedInstanceState)
setContentView(R.layout. activity_main )
recyclerView = findViewById(R.id. recyclerView )
recyclerView . layoutManager = LinearLayoutManager( this )
bookAdapter = BookAdapter(getAllBooksFromDatabase())
recyclerView . adapter = bookAdapter
checkEmptyViewVisibility()
//
val dbHelper = DatabaseHelper(this, "BookStore.db", 2)
//
val createDatabase =
findViewById<Button>(R.id.createDatabase)
//
createDatabase.setOnClickListener {
//
dbHelper.writableDatabase
//
}
val addData = findViewById<Button>(R.id. addData )
addData.setOnClickListener {
val intent = Intent( this @MainActivity ,
AddBookActivity:: class . java )
startActivity(intent)
}
}
private fun getAllBooksFromDatabase (): List<Book> { val dbHelper = DatabaseHelper( this, "BookStore.db" , 2 )
val db = dbHelper. readableDatabase
val query = "SELECT * FROM Book"
val cursor = db.rawQuery(query , null )
val books = mutableListOf <Book>()
while (cursor.moveToNext()) {
val nameIndex = cursor.getColumnIndex( "name" )
val authorIndex = cursor.getColumnIndex( "author" )
val priceIndex = cursor.getColumnIndex( "price" )
val categoryIdIndex =
cursor.getColumnIndex( "categoryId" )
val name: String? = cursor.getString(nameIndex)
val author: String? = cursor.getString(authorIndex)
val price: Double = cursor.getDouble(priceIndex)
val categoryId: Int = cursor.getInt(categoryIdIndex)
// 使用空字符串作为默认值
val book = Book(author ?: "" , price , 0 , name ?: "" ,
categoryId)
books.add(book)
}
cursor.close()
return books
}
private fun checkEmptyViewVisibility () {
emptyView = findViewById(R.id. emptyTextView )
if ( bookAdapter . itemCount == 0 ) {
emptyView . visibility = View. VISIBLE
} else {
emptyView . visibility = View. GONE
}
}
}
activity_main.xml
<? xml version ="1.0" encoding ="utf-8" ?>
<LinearLayout xmlns: android ="http://schemas.android.com/apk/res/android"
android :orientation ="vertical"
android :layout_width ="match_parent"
android :layout_height ="match_parent" >
<androidx.recyclerview.widget.RecyclerView
android :id ="@+id/recyclerView"
android :layout_width ="match_parent"
android :layout_height ="wrap_content"
android :layout_weight ="1"
android :scrollbars ="vertical" />
<TextView
android :id ="@+id/emptyTextView"
android :layout_width ="match_parent"
android :layout_height ="wrap_content"
android :gravity ="center"
android :visibility ="gone"
android :text ="No books available"
android :textSize ="20sp"
/>
<!--
<Button-->
<!--
android:id="@+id/createDatabase"-->
<!--
android:layout_width="match_parent"-->
<!--
android:layout_height="wrap_content"-->
<!--
android:text="Create Database" />-->
<Button
android :id ="@+id/addData"
android :layout_width ="match_parent"
android :layout_height ="wrap_content"
android :text ="Add Book" />
<!--
<TextView-->
<!--
android:id="@+id/androidTextView"-->
<!--
android:layout_width="wrap_content"-->
<!--
android:layout_height="wrap_content"-->
<!--
android:text="Android Text" />-->
<!--
<Button-->
<!--
android:id="@+id/updateData"-->
<!--
android:layout_width="match_parent"-->
<!--
android:layout_height="wrap_content"-->
<!--
android:text="Update Data" />-->
<!--
<Button-->
<!--
android:id="@+id/deleteData"-->
<!--
android:layout_width="match_parent"-->
<!--
android:layout_height="wrap_content"-->
<!--
android:text="Delete Data" />-->
<!--
<Button--> 15
<!--
android:id="@+id/queryData"-->
<!--
android:layout_width="match_parent"-->
<!--
android:layout_height="wrap_content"-->
<!--
android:text="Query Data"/>-->
</LinearLayout>
DataBaseHelper.kt
package com.example.mylibrary
import android.content.ContentValues
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import android.widget.Toast
class DatabaseHelper(context: Context , name: String , version: Int) :
SQLiteOpenHelper(context , name , null, version) {
private val createBook = "create table Book (" +
"id integer primary key autoincrement," +
"author text," +
"price real," +
"pages integer," +
"name text," +
"categoryId integer)"
private val createCategory = "create table Category (" +
"id integer primary key autoincrement," +
"category_name text," +
"category_code integer)"
override fun onCreate (db: SQLiteDatabase) {
db.execSQL( createBook )
db.execSQL( createCategory )
//
Toast.makeText(this@DatabaseHelper, "Tables created
successfully", Toast.LENGTH_SHORT).show()
// 插入经济类别记录
val contentValues = ContentValues(). apply {
put( "category_name" , " 经济类 " )
put( "category_code" , 1 )
} 16
db.insert( "Category" , null, contentValues)
}
override fun onUpgrade (db: SQLiteDatabase , oldVersion: Int , newVersion:
Int) {
db.execSQL( "DROP TABLE IF EXISTS Book" )
db.execSQL( "DROP TABLE IF EXISTS Category" )
onCreate(db)
}
}
AddBookActivity.kt
package com.example.mylibrary
import android.content.ContentValues
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
class AddBookActivity : AppCompatActivity() {
//
private lateinit var dbHelper: DatabaseHelper
override fun onCreate (savedInstanceState: Bundle?) {
super .onCreate(savedInstanceState)
setContentView(R.layout. activity_add_book )
//
dbHelper = DatabaseHelper(this)
val dbHelper =DatabaseHelper( this, "BookStore.db" , 2 )
val addBookButton: Button = findViewById(R.id. addBookButton )
addBookButton.setOnClickListener {
val nameEditText: EditText = findViewById(R.id. nameEditText )
val authorEditText: EditText = findViewById(R.id. authorEditText )
//
val category: EditText =
findViewById(R.id.categoryIdEditText)
val priceEditText: EditText = findViewById(R.id. priceEditText )
val categoryIdEditText: EditText =
findViewById(R.id. categoryIdEditText )
val name = nameEditText. text .toString()
val author = authorEditText. text .toString() 17
//
val pages = pagesEditText.text.toString().toIntOrNull() ?: 0
// 处理无效输入
val price = priceEditText. text .toString(). toDoubleOrNull () ?:
0.0 // 处理无效输入
val categoryId =
categoryIdEditText. text .toString(). toIntOrNull () ?: 0 // 处理无效输入
val db = dbHelper. writableDatabase
val values = ContentValues(). apply {
put( "name" , name)
put( "author" , author)
put( "categoryId" , categoryId)
put( "price" , price)
//
put("categoryId", categoryId)
}
val newRowId = db.insert( "Book" , null, values)
if (newRowId == - 1L ) {
// 插入失败
Toast.makeText( this, " 添加书籍到数据库失败 " ,
Toast. LENGTH_SHORT ).show()
} else {
// 插入成功
Toast.makeText( this, " 书籍已添加到数据库 " ,
Toast. LENGTH_SHORT ).show()
}
// 清空输入框
nameEditText. text .clear()
authorEditText. text .clear()
categoryIdEditText. text .clear()
priceEditText. text .clear()
//
categoryIdEditText.text.clear()
val intent = Intent( this @AddBookActivity ,
MainActivity:: class . java )
startActivity(intent)
//
finish();
}
}
}
activity_add_book.xml
<? xml version ="1.0" encoding ="utf-8" ?> <RelativeLayout
xmlns: android ="http://schemas.android.com/apk/res/android"
android :layout_width ="match_parent"
android :layout_height ="match_parent"
android :padding ="16dp" >
<EditText
android :id ="@+id/authorEditText"
android :layout_width ="match_parent"
android :layout_height ="wrap_content"
android :hint ="Author"
android :layout_marginBottom ="16dp"
android :minWidth ="200dp"
android :minHeight ="48dp"
android :padding ="8dp" />
<EditText
android :id ="@+id/priceEditText"
android :layout_width ="match_parent"
android :layout_height ="wrap_content"
android :inputType ="numberDecimal"
android :hint ="Price"
android :layout_below ="@id/authorEditText"
android :layout_marginBottom ="16dp"
android :minWidth ="200dp"
android :minHeight ="48dp"
android :padding ="8dp" />
<EditText
android :id ="@+id/pagesEditText"
android :layout_width ="match_parent"
android :layout_height ="wrap_content"
android :inputType ="number"
android :hint ="Pages"
android :layout_below ="@id/priceEditText"
android :layout_marginBottom ="16dp"
android :minWidth ="200dp"
android :minHeight ="48dp"
android :padding ="8dp" />
<EditText
android :id ="@+id/nameEditText"
android :layout_width ="match_parent"
android :layout_height ="wrap_content"
18 android :hint ="Name"
android :layout_below ="@id/pagesEditText"
android :layout_marginBottom ="16dp"
android :minWidth ="200dp"
android :minHeight ="48dp"
android :padding ="8dp" />
<EditText
android :id ="@+id/categoryIdEditText"
android :layout_width ="match_parent"
android :layout_height ="wrap_content"
android :inputType ="number"
android :hint ="Category ID"
android :layout_below ="@id/nameEditText"
android :layout_marginBottom ="16dp"
android :minWidth ="200dp"
android :minHeight ="48dp"
android :padding ="8dp" />
<Button
android :id ="@+id/addBookButton"
android :layout_width ="wrap_content"
android :layout_height ="wrap_content"
android :text ="Add Book"
android :layout_centerInParent ="true" />
<androidx.recyclerview.widget.RecyclerView
android :id ="@+id/recyclerView"
android :layout_width ="match_parent"
android :layout_height ="match_parent"
android :layout_above ="@id/addBookButton"
android :layout_marginBottom ="16dp" />
</RelativeLayout>
BookAdapter.kt
// BookAdapter.kt
package com.example.mylibrary
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
class BookAdapter( private val bookList : List<Book>) :
RecyclerView.Adapter<BookAdapter.BookViewHolder>() {
class BookViewHolder(itemView: View) :
RecyclerView.ViewHolder(itemView) {
val titleTextView : TextView =
itemView.findViewById(R.id. textViewTitle )
val authorTextView : TextView =
itemView.findViewById(R.id. textViewAuthor )
val categoryTextView : TextView =
itemView.findViewById(R.id. textViewCategory )
val priceTextView : TextView =
itemView.findViewById(R.id. textViewPrice )
}
override fun onCreateViewHolder (parent: ViewGroup , viewType: Int):
BookViewHolder {
val itemView = LayoutInflater.from(parent. context )
.inflate(R.layout. item_book , parent , false )
return BookViewHolder(itemView)
}
override fun onBindViewHolder (holder: BookViewHolder , position: Int) {
val currentItem = bookList [position]
holder. titleTextView . text = currentItem. name
holder. authorTextView . text = currentItem. author
holder. categoryTextView . text = currentItem. categoryId .toString()
holder. priceTextView . text = currentItem. price .toString()
}
override fun getItemCount () = bookList . size
}
item_book,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 ="wrap_content"
android :orientation ="vertical" >
<TextView
android :id ="@+id/textViewTitle"
android :layout_width ="wrap_content"
android :layout_height ="wrap_content"
android :textSize ="18sp"
android :textStyle ="bold"
android :text ="Title" />
<TextView
android :id ="@+id/textViewAuthor"
android :layout_width ="wrap_content"
android :layout_height ="wrap_content"
android :textSize ="16sp"
android :text ="Author"
/>
<TextView
android :id ="@+id/textViewCategory"
android :layout_width ="wrap_content"
android :layout_height ="wrap_content"
android :textSize ="14sp"
android :text ="Category"
/>
<TextView
android :id ="@+id/textViewPrice"
android :layout_width ="wrap_content"
android :layout_height ="wrap_content"
android :textSize ="14sp"
android :text ="Price"
/>
</LinearLayout>
  • 34
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

塔塔o

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值