又是学到了数据持久化。
登录界面
题外话:有无动画大佬带带呀,前端移动端可免( •̀ .̫ •́ ),合作可私信哦。
1.用户登陆和“记住我”功能
该内容拥有两个Activity活动视图:
(1)LoginActivity(LoginActivity.kt、activity_login.xml):登陆和注册Activity,具备用户登录和记住帐户密码的功能;
(2)MainActivity(MainActivity.kt、activity_main.xml):登陆成功后显示的主页面,显示“登陆成功!”(TextView)。
在登陆活动LoginActivity中,可基于“实验4界面设计1”的登陆Activity进行开发设计,包含的控件有:
(1)“用户名”和“密码”的输入框(EditText)和对应的文本说明(TextView),
(2)“注册”按钮(Button)
(3)“登陆”按钮(Button)
(4)“记住我”勾选框(CheckBox)
实现以下功能(需求):
(1)普通登陆成功:用户可以输入用户名和密码,然后点击“登陆”,如果用户名和密码正确,即可登录,跳转到MainActivity中。
(2)普通登陆失败:用户可以输入用户名和密码,然后点击“登陆”,如果用户名或密码不正确,弹出警告对话窗(参考4.2.6节),提醒用户重新输入。
(3)“记住我“登陆成功:用户可以输入用户名和密码,勾选“记住我”勾选框后,然后点击“登陆”,如果用户名和密码正确,即可登录,此时会跳转到MainActivity。同时,根据勾选“记住我”作为条件判断,记住当前正确验证的用户名和密码信息。那么,在下一次打开应用的LoginActivity时,会自动填写用户名和密码信息。
(4)“记住我“登陆失败:用户可以输入用户名和密码,勾选“记住我”勾选框后,然后点击“登陆”,如果用户名或密码不正确,弹出警告对话窗,提醒用户重新输入。同时,不会根据“记住我”勾选框进行用户名和密码信息的保存。
(5)用户名和密码信息保存:通过SharedPreferences方式进行保存,文件名命名为“remember”。
(6)用户注册:用户可在“用户名”和“密码”的输入框进行输入,点击“注册”即可注册帐户。注册时,需要检查用户名是否重复,如果重复,则弹出警告对话框提醒;如果不重复,则弹出Toast显示“注册成功”提醒注册成功。
(7)用户注册信息保存:成功注册的帐户,以文件存储方式,将文件名命名为“accounts”来保存用户名和密码信息,用户名和密码信息按以下格式进行保存:
用户名1,密码1
用户名2,密码2
用户名3,密码3
解释:用户名和密码以英文逗号隔开,每一行保存一个帐户信息。
这道题的主活动就是一行文本很简单,所以主活动改为下一题的,即可以先写一个登录界面,然后直接进入主界面进行添加图书。
LoginActivity.kt
package com.example.t8
import android.content.Context
import android.content.Intent
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
import androidx.appcompat.app.AlertDialog
class LoginActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login) // 修正了布局文件名称
val userNameEditText: EditText = findViewById(R.id.userName)
val passWordEditText: EditText = findViewById(R.id.passWord)
val rememberMeCheckBox: CheckBox = findViewById(R.id.rememberMe)
// 获取 SharedPreferences
val prefs = getPreferences(Context.MODE_PRIVATE)
val isRememberMe = prefs.getBoolean("remember_me", false)
// 如果记住密码,设置已保存的用户名和密码
if (isRememberMe) {
val username = prefs.getString("username", "") ?: ""
val password = prefs.getString("password", "") ?: ""
userNameEditText.setText(username)
passWordEditText.setText(password)
rememberMeCheckBox.isChecked = true
}
// 注册按钮点击事件
val registerButton: Button = findViewById(R.id.register)
registerButton.setOnClickListener {
val username = userNameEditText.text.toString()
val password = passWordEditText.text.toString()
if (prefs.contains(username)) {
AlertDialog.Builder(this)
.setTitle("注册失败")
.setMessage("用户名已存在,请重新输入!")
.setPositiveButton("确定", null)
.show()
} else if (username.isEmpty()) {
Toast.makeText(this, "用户名不能为空", Toast.LENGTH_SHORT).show()
} else if (password.isEmpty()) {
Toast.makeText(this, "密码不能为空", Toast.LENGTH_SHORT).show()
} else {
val editor = prefs.edit()
editor.putString(username, password)
editor.apply()
Toast.makeText(this, "注册成功", Toast.LENGTH_SHORT).show()
userNameEditText.text.clear()
passWordEditText.text.clear()
}
}
// 登录按钮点击事件
val loginButton: Button = findViewById(R.id.login)
loginButton.setOnClickListener {
val username = userNameEditText.text.toString()
val password = passWordEditText.text.toString()
if (prefs.getString(username, "") == password) {
val editor = prefs.edit()
if (rememberMeCheckBox.isChecked) {
editor.putBoolean("remember_me", true)
editor.putString("username", username)
editor.putString("password", password)
} else {
editor.clear()
}
editor.apply()
// 登录成功,跳转到 MainActivity
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
finish()
} else if (username.isEmpty()) {
Toast.makeText(this, "用户名不能为空", Toast.LENGTH_SHORT).show()
} else if (password.isEmpty()) {
Toast.makeText(this, "密码不能为空", Toast.LENGTH_SHORT).show()
} else {
AlertDialog.Builder(this)
.setTitle("登录失败")
.setMessage("用户名或密码错误")
.setPositiveButton("确定", null)
.show()
}
}
}
}
activity_login.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- First LinearLayout (for username and password input) -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="80dp"
android:orientation="horizontal"
android:gravity="bottom">
<TextView
android:id="@+id/textName"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="@string/username"
android:textSize="23sp"
android:layout_gravity="center"
android:layout_marginStart="16dp" />
<EditText
android:id="@+id/userName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="@string/enter_username"
android:textSize="23sp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="16dp" />
</LinearLayout>
<!-- Second LinearLayout (for password input) -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="80dp"
android:orientation="horizontal"
android:gravity="bottom">
<TextView
android:id="@+id/textPwd"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="@string/password"
android:textSize="23sp"
android:gravity="center"
android:layout_marginStart="16dp" />
<EditText
android:id="@+id/passWord"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="请输入密码"
android:textSize="23sp"
android:gravity="center_vertical"
android:layout_marginEnd="16dp"
android:inputType="textPassword" />
</LinearLayout>
<!-- Third LinearLayout (for remember me checkbox) -->
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<CheckBox
android:id="@+id/rememberMe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="17dp"
android:layout_marginStart="25dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="22sp"
android:layout_marginTop="20dp"
android:text="@string/remember_me" />
</LinearLayout>
<!-- Fourth LinearLayout (for login and register buttons) -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp"
android:layout_gravity="center">
<Button
android:id="@+id/login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/login"
android:textSize="24sp"
android:layout_margin="10dp" />
<Button
android:id="@+id/register"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/register"
android:textSize="24sp"
android:layout_margin="10dp" />
</LinearLayout>
</LinearLayout>
strings.xml
<resources>
<string name="app_name">T8</string>
<string name="username">用户名:</string>
<string name="enter_username">请输入用户名</string>
<string name="password">密码:</string>
<string name="enter_password">请输入密码</string>
<string name="login">登录</string>
<string name="register">注册</string>
<string name="remember_me">记住我</string>
</resources>
登录后,怎样查看SharedPreferences存储的remember与文件存储的accounts,找到androidstudio的工具栏,点击 View
-> Tool Windows
-> Device File Explorer
打开,然后找到/data/data/<your.app.package.name>/shared_prefs/与/data/data/<your.app.package.name>/files/,双击即可。
remember.xml文件
accounts文件
图书馆界面
本题主要为SQLite数据库进行数据存储,也是特别重要的一种存储方式,SQLite数据库在很多设备的应用还是比较多的。
实现一个“网上图书馆”。
需要保存的信息:书本信息和书本所属类别。每本书有其所属的类别。
create table Book ( category_id integer ) | create table Category ( |
使用SqlLite数据库创建数据库library,并创建Book和Category这两个表。往Category里插入2条默认书类别数据(如:经济类, 1)。
界面设计:
创建一个MainActivity,对应的布局为activity_main。
添加一个RecyclerView,用于显示所有的图书条目信息,每个条目显示书的名字、作者、类别和价格。
添加一个“添加书目”的按钮,用于跳转进入AddBookActivity。
④ 在AddBookActivity中,可以添加一本书的信息到数据库中。提示:AddBookActivity需要的组件包括:EditText、TextView、Button或Spinner。
提醒:可以在RecyclerView的适配器里面进行数据库的查询操作。
MainActivity
package com.example.t8
import android.annotation.SuppressLint
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
class MainActivity : AppCompatActivity() {
private lateinit var recyclerView: RecyclerView
private lateinit var bookListAdapter: BookListAdapter // 书籍列表的适配器
private lateinit var emptyView: TextView // 空视图
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 设置 RecyclerView 的布局管理器和适配器
recyclerView = findViewById(R.id.recyclerView)
recyclerView.layoutManager = LinearLayoutManager(this)
bookListAdapter = BookListAdapter(getAllBooks())
recyclerView.adapter = bookListAdapter
emptyView = findViewById(R.id.emptyTextView)
// 设置添加书籍按钮的点击事件
val addBookButton: Button = findViewById(R.id.addBookButton)
addBookButton.setOnClickListener {
val intent = Intent(this, AddBookActivity::class.java)
startActivityForResult(intent, ADD_BOOK_REQUEST_CODE)
}
updateBookList()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == ADD_BOOK_REQUEST_CODE && resultCode == RESULT_OK) {
// 如果是从添加书籍界面返回且成功添加了书籍,则更新书籍列表
updateBookList()
}
}
private fun updateBookList() {
val books = getAllBooks()
bookListAdapter.updateBooks(books)
checkViewVisibility()
}
@SuppressLint("Range")
private fun getAllBooks(): List<Book> {
val databaseHelper = DatabaseHelper(this, "library.db", 3)
val db = databaseHelper.readableDatabase
val query = "SELECT * FROM Book"
val cursor = db.rawQuery(query, null)
val books = mutableListOf<Book>()
while (cursor.moveToNext()) {
val id = cursor.getInt(cursor.getColumnIndex("id"))
val name = cursor.getString(cursor.getColumnIndex("name"))
val author = cursor.getString(cursor.getColumnIndex("author"))
val price = cursor.getDouble(cursor.getColumnIndex("price"))
val pages = cursor.getInt(cursor.getColumnIndex("pages"))
val categoryId = cursor.getInt(cursor.getColumnIndex("category_id"))
val book = Book(id, name, author, price, pages, categoryId)
books.add(book)
}
cursor.close()
return books
}
private fun checkViewVisibility() {
val isEmpty = bookListAdapter.itemCount == 0
emptyView.visibility = if (isEmpty) View.VISIBLE else View.GONE
// 控制其他视图的显示/隐藏
findViewById<TextView>(R.id.BookName).visibility = if (!isEmpty) View.VISIBLE else View.GONE
findViewById<TextView>(R.id.BookAuthor).visibility = if (!isEmpty) View.VISIBLE else View.GONE
findViewById<TextView>(R.id.BookPrice).visibility = if (!isEmpty) View.VISIBLE else View.GONE
findViewById<TextView>(R.id.BookCategory).visibility = if (!isEmpty) View.VISIBLE else View.GONE
}
companion object {
private const val ADD_BOOK_REQUEST_CODE = 1
}
}
activity_main
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:padding="16dp"
tools:context=".MainActivity">
<Button
android:id="@+id/addBookButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="15dp"
android:text="添加图书" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp">
<TextView
android:id="@+id/BookName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="@android:color/black"
android:textSize="26sp"
android:textStyle="bold"
android:text="书名" />
<TextView
android:id="@+id/BookAuthor"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="@android:color/black"
android:textSize="26sp"
android:textStyle="bold"
android:text="作者"
android:visibility="gone" />
<TextView
android:id="@+id/BookPrice"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="@android:color/black"
android:textSize="26sp"
android:textStyle="bold"
android:text="价格"
android:visibility="gone" />
<TextView
android:id="@+id/BookCategory"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="@android:color/black"
android:textSize="26sp"
android:textStyle="bold"
android:text="分类"
android:visibility="gone" />
</LinearLayout>
<TextView
android:id="@+id/emptyTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="300dp"
android:visibility="gone"
android:text="暂无图书!"
android:textSize="20sp" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Book
package com.example.t8
data class Book(
val id: Int,
val name: String,
val author: String,
val price: Double,
val pages: Int,
val categoryId: Int
)
BookListAdapter
package com.example.t8
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
class BookListAdapter(private var bookList: List<Book>) :
RecyclerView.Adapter<BookListAdapter.BookViewHolder>() {
class BookViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val nameTextView: TextView = itemView.findViewById(R.id.nameTextView)
val authorTextView: TextView = itemView.findViewById(R.id.authorTextView)
val priceTextView: TextView = itemView.findViewById(R.id.priceTextView)
val categoryTextView: TextView = itemView.findViewById(R.id.categoryTextView)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BookViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_book, parent, false)
return BookViewHolder(view)
}
override fun onBindViewHolder(holder: BookViewHolder, position: Int) {
val book = bookList[position]
holder.nameTextView.text = book.name
holder.authorTextView.text = book.author
holder.priceTextView.text = book.price.toString()
holder.categoryTextView.text = book.categoryId.toString()
}
override fun getItemCount(): Int {
return bookList.size
}
@SuppressLint("NotifyDataSetChanged")
fun updateBooks(newBookList: List<Book>) {
bookList = newBookList
notifyDataSetChanged()
}
}
Category
package com.example.t8
data class Category(val id: Int, val categoryName: String, val categoryCode: Int)
CategoryAdapter
class CategoryAdapter(context: Context, private val categories: List<Category>) :
ArrayAdapter<Category>(context, android.R.layout.simple_spinner_item, categories) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view = super.getView(position, convertView, parent)
val textView = view.findViewById<TextView>(android.R.id.text1)
textView.text = categories[position].categoryName // 设置下拉框中显示的文本为类别名称
return view
}
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
val view = super.getDropDownView(position, convertView, parent)
val textView = view.findViewById<TextView>(android.R.id.text1)
textView.text = categories[position].categoryName // 设置下拉框中下拉选项的文本为类别名称
return view
}
override fun getItem(position: Int): Category? {
return categories[position] // 返回指定位置的Category对象
}
}
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"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp">
<!-- 书名 -->
<TextView
android:id="@+id/nameTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="18sp"
android:textColor="@android:color/darker_gray" />
<!-- 作者 -->
<TextView
android:id="@+id/authorTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="18sp"
android:textColor="@android:color/darker_gray" />
<!-- 价格 -->
<TextView
android:id="@+id/priceTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="18sp"
android:textColor="@android:color/darker_gray" />
<!-- 分类 -->
<TextView
android:id="@+id/categoryTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="18sp"
android:textColor="@android:color/darker_gray" />
</LinearLayout>
</LinearLayout>
AddBookActivity
package com.example.t8
import android.content.ContentValues
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.*
class AddBookActivity : AppCompatActivity() {
private lateinit var databaseHelper: DatabaseHelper
private lateinit var spinnerCategory: Spinner
private lateinit var categories: List<Category> // 保存类别的列表
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_add_book)
// 初始化数据库帮助类
databaseHelper = DatabaseHelper(this, "library.db", 3)
insertInitialCategories()
// 初始化类别选择下拉框
spinnerCategory = findViewById(R.id.spinnerCategory)
// 获取所有类别并赋值给 categories
categories = databaseHelper.getAllCategories()
// 获取类别名称列表,并将其填充到下拉框中
val categoryNames = categories.map { it.categoryName }
val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, categoryNames)
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
spinnerCategory.adapter = adapter
// 设置添加书籍按钮的点击事件
val btnAddBook: Button = findViewById(R.id.btnAddBook)
btnAddBook.setOnClickListener {
addBook()
}
}
private fun addBook() {
val editTextName: EditText = findViewById(R.id.editTextName)
val editTextAuthor: EditText = findViewById(R.id.editTextAuthor)
val editTextPrice: EditText = findViewById(R.id.editTextPrice)
val editTextPages: EditText = findViewById(R.id.editTextPages)
spinnerCategory = findViewById(R.id.spinnerCategory)
val name = editTextName.text.toString().trim()
val author = editTextAuthor.text.toString().trim()
val price = editTextPrice.text.toString().toDoubleOrNull() ?: 0.0
val pages = editTextPages.text.toString().trim()
val selectedCategoryName = spinnerCategory.selectedItem as String
// 根据选择的类别名称,查找对应的 Category 对象
val selectedCategory = categories.find { it.categoryName == selectedCategoryName }
// 确保选中的类别不为 null
selectedCategory?.let {
val db = databaseHelper.writableDatabase
val values = ContentValues().apply {
put("name", name)
put("author", author)
put("pages", pages)
put("price", price)
put("category_id", it.id) // 使用 selectedCategory 的 id 字段
}
// 插入新的书籍记录
val newRowId = db.insert("Book", null, values)
if (newRowId != -1L) {
// 插入成功后,可以添加提示信息或者返回上一界面等操作
setResult(RESULT_OK)
finish()
} else {
// 插入失败的处理
Toast.makeText(this, "添加书籍失败", Toast.LENGTH_SHORT).show()
}
} ?: run {
// 如果没有选择类别,提示用户
Toast.makeText(this, "请选择类别", Toast.LENGTH_SHORT).show()
}
}// 插入初始类别数据的方法
private fun insertInitialCategories() {
// 检查数据库中是否已经有类别数据
if (databaseHelper.getAllCategories().isEmpty()) {
databaseHelper.insertCategory("经济类", 1)
databaseHelper.insertCategory("武侠类", 2)
databaseHelper.insertCategory("医药类", 3)
// 可以根据需要添加更多类别
}
}
}
DatabaseHelper
package com.example.t8
import android.annotation.SuppressLint
import android.content.ContentValues
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import android.widget.Toast
class DatabaseHelper(private val 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,
category_id 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(context, "Create succeeded", Toast.LENGTH_SHORT).show()
}
// 更新数据库时删除旧表并创建新表
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)
}
// 插入类别
fun insertCategory(categoryName: String, categoryCode: Int) {
val db = this.writableDatabase
val contentValues = ContentValues().apply {
put("category_name", categoryName)
put("category_code", categoryCode)
}
db.insert("Category", null, contentValues)
db.close()
}
// 获取所有类别
@SuppressLint("Range")
fun getAllCategories(): List<Category> {
val categoryList = mutableListOf<Category>()
val db = this.readableDatabase
val cursor = db.rawQuery("SELECT * FROM Category", null)
cursor.use {
if (it.moveToFirst()) {
do {
val id = it.getInt(it.getColumnIndex("id"))
val categoryName = it.getString(it.getColumnIndex("category_name"))
val categoryCode = it.getInt(it.getColumnIndex("category_code"))
val category = Category(id, categoryName, categoryCode)
categoryList.add(category)
} while (it.moveToNext())
}
}
cursor.close()
return categoryList
}
}
activity_add_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="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:padding="16dp"
tools:context=".AddBookActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="80dp"
android:gravity="bottom"
android:orientation="horizontal">
<!-- 书名 -->
<TextView
android:id="@+id/textViewName"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="16dp"
android:text="书名"
android:textSize="23sp" />
<EditText
android:id="@+id/editTextName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:layout_marginEnd="16dp"
android:layout_weight="1"
android:hint="请输入书名"
android:inputType="text"
android:textSize="23sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="80dp"
android:gravity="bottom"
android:orientation="horizontal">
<!-- 作者 -->
<TextView
android:id="@+id/textViewAuthor"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="16dp"
android:text="作者"
android:textSize="23sp" />
<EditText
android:id="@+id/editTextAuthor"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:layout_marginEnd="16dp"
android:layout_weight="1"
android:hint="请输入作者"
android:inputType="text"
android:textSize="23sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="80dp"
android:gravity="bottom"
android:orientation="horizontal">
<!-- 价格 -->
<TextView
android:id="@+id/textViewPrice"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="16dp"
android:text="价格"
android:textSize="23sp" />
<EditText
android:id="@+id/editTextPrice"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:layout_marginEnd="16dp"
android:layout_weight="1"
android:hint="请输入价格"
android:inputType="numberDecimal"
android:textSize="23sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="bottom"
android:orientation="horizontal">
<!-- 页数 -->
<TextView
android:id="@+id/textViewPages"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="16dp"
android:text="页数"
android:textSize="23sp" />
<EditText
android:id="@+id/editTextPages"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:layout_marginEnd="16dp"
android:layout_weight="1"
android:hint="请输入页数"
android:inputType="number"
android:textSize="23sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/layoutCategory"
android:layout_width="match_parent"
android:layout_height="58dp"
android:layout_marginTop="8dp"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="8dp">
<Spinner
android:id="@+id/spinnerCategory"
android:layout_width="match_parent"
android:layout_height="48dp"
android:textSize="23sp" />
</LinearLayout>
<!-- 添加书目按钮 -->
<Button
android:id="@+id/btnAddBook"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="16dp"
android:text="添加书目" />
</LinearLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.t8">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.T8">
<activity
android:name=".MainActivity"
android:exported="false" />
<activity
android:name=".AddBookActivity"
android:exported="false" />
<activity
android:name=".LoginActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
然后怎么查看sqlite数据库存储的数据,与上题类似,进到 /data/data/<your.app.package.name>/databases/找到db文件即可。
在这里你会遇到一个问题,怎么双击打不开了,叉掉后进入本地文件夹的存储去了。是的,直接点是打不开的,当你进到文件夹发现这个library文件时拷贝一份,放到你想放的文件夹路径,然后记住这个存放的文件夹路径。接着可以用一些数据库可视化界面管理工具进行连接查看,这里用的是navicat。打开navicat,新建sqlite数据库的连接。
在数据库文件选取你刚刚存放的路径即可,然后就可以查看了。
实验心得
那天,他等到了不下雨,却没有等到天晴。