草庐IT

Kotlin实现简单的学生信息管理系统

振华OPPO 2023-04-16 原文

文章目录

一、实验内容

根据Android数据存储的内容,综合应用SharedPreferences和SQLite数据库实现一个用户信息管理系统,强化对SharedPreferences的理解的使用,熟练掌握SQLite的操作。要求:

  1. 巩固Android应用开发工具(Eclipse或者AndroidStudio)的常规用法;
  2. 巩固Activity、UI控件的常规用法;
  3. 掌握SharedPpreferences数据存储的使用;
  4. 掌握SQLite数据库及SQLiteOpenHelper的使用。

二、实验步骤

1、页面布局

本次布局提倡从简原则,按照往常习惯,我肯定是创建多个Activity,然后每个Activity设置下页面,分别从主页面跳转到各个页面。既然是实验,那就从简,实现核心的思想就可以了,底层逻辑实现出来,表面内容那不是花时间设计下就行了。言归正传,主页面布局如下,没有任何亮点可言,比较常规,只给Button和TextView都设置了background。


完整的layout代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <EditText
        android:id="@+id/et_id"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入学号"
        android:textSize="20sp"
        android:textColor="@color/black"
        android:padding="10dp"
        android:layout_margin="20dp"
        android:inputType="text"
        android:background="@drawable/et_selector" />
    <EditText
        android:id="@+id/et_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入姓名"
        android:textSize="20sp"
        android:textColor="@color/black"
        android:padding="10dp"
        android:layout_margin="20dp"
        android:inputType="text"
        android:background="@drawable/et_selector" />
    <EditText
        android:id="@+id/et_age"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入年龄"
        android:textSize="20sp"
        android:textColor="@color/black"
        android:padding="10dp"
        android:layout_margin="20dp"
        android:inputType="text"
        android:background="@drawable/et_selector" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:id="@+id/btn_insert"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:text="添加"
            android:background="@drawable/btn_selector"
            android:textSize="20sp"
            android:layout_margin="10dp"
            android:textColor="@color/black"/>
        <Button
            android:id="@+id/btn_delete"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:text="删除"
            android:background="@drawable/btn_selector"
            android:textSize="20sp"
            android:layout_margin="10dp"
            android:textColor="@color/black"/>
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginBottom="20dp">
        <Button
            android:id="@+id/btn_update"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:text="修改"
            android:background="@drawable/btn_selector"
            android:textSize="20sp"
            android:layout_margin="10dp"
            android:textColor="@color/black"/>
        <Button
            android:id="@+id/btn_query"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:text="查询"
            android:background="@drawable/btn_selector"
            android:textSize="20sp"
            android:layout_margin="10dp"
            android:textColor="@color/black"/>
    </LinearLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="@color/black"/>
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="0dp"
            android:layout_weight="1"
            android:text="学号"
            android:textSize="20sp"
            android:gravity="center"
            android:layout_height="wrap_content"/>
        <TextView
            android:layout_width="0dp"
            android:layout_weight="1"
            android:text="姓名"
            android:textSize="20sp"
            android:gravity="center"
            android:layout_height="wrap_content"/>
        <TextView
            android:layout_width="0dp"
            android:layout_weight="1"
            android:text="年龄"
            android:textSize="20sp"
            android:gravity="center"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="@color/black"/>
    <ListView
        android:id="@+id/lv_stu"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

2、数据库

考查对SQLite的熟练程度,其实就是Android提供了一个数据库帮助类,帮我们进行数据库的各种操作。我们要做的就是建库建表,写个增删改查的方法,然后剩下的事情交给系统。这里是学生表的建表语句,一切属性都能用text表示。

    private val CREATE_STUDENT = "create table Student (" +
            "id text primary key," +
            "name text," +
            "age text)"

再看学生类,简直封装的太好了,Kotlin的魅力所在,换做Java又是属性、构造函数、get和set方法。

class Student(val id:String, val name:String, val age:String) {

}

下面看数据库的增删改查操作,所有的操作都是针对数据库的Student表来的,增加、删除和修改都很简单,使用ContentValues添加键值对。查询是最关键的,使用cursor游标一行行遍历表数据,各种约束条件可以自己加,正常全查就完事了。

 val dbHelper = DBHelper(context, "stu.db", 1)
    lateinit var db:SQLiteDatabase

    fun openDB() {
        db = dbHelper.writableDatabase
    }

    fun closeDB() {
        if (db != null) dbHelper.close()
    }
    // 插入学生
    fun insertStudent(stu: Student) {
        val values = ContentValues().apply {
            put("id", stu.id)
            put("name", stu.name)
            put("age", stu.age)
        }
        db.insert("Student", null, values)
    }
    // 删除学生
    fun deleteStudent(stu: Student) {
        db.delete("Student", "id = ?", arrayOf(stu.id))
    }
    // 更新学生
    fun updateStudent(stu: Student) {
        val values = ContentValues()
        values.put("name", stu.name)
        values.put("age", stu.age)
        db.update("Student", values, "id = ?", arrayOf(stu.id))
    }
    // 查询所有学生
    fun queryAllStudent():ArrayList<Student> {
        val cursor = db.query("Student", null, null, null, null, null, null)
        val stuList = ArrayList<Student>()
        if (cursor.moveToFirst()) {
            do {
                val id = cursor.getString(cursor.getColumnIndex("id"))
                val name = cursor.getString(cursor.getColumnIndex("name"))
                val age = cursor.getString(cursor.getColumnIndex("age"))
                val stu = Student(id, name, age)
                stuList.add(stu)
            } while (cursor.moveToNext())
        }
        cursor.close()
        return stuList
    }

3、登录活动

登录活动用的是sharedPreferences,它使用方法非常easy,首先初始化一个sharedPreferences对象,文件名和访问类型自定义。读数据就是调用getString获取键值对,设定个默认值。写数据就是调用sharedPreferences.edit()赋值给editor对象,然后putString读取键值对。还记录了下app的使用次数。

	override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityLoginBinding.inflate(layoutInflater)
        setContentView(binding.root)
        sharedPreferences = getSharedPreferences("data", Context.MODE_PRIVATE)
        var editor = sharedPreferences.edit()
        // 得到之前的使用次数,然后每次打开app都加1
        var count = sharedPreferences.getString("count", "0");
        binding.tvCount.text = (count!!.toInt() + 1).toString()
        // 保存键值对到sharedpreferences中
        editor.putString("count", (count!!.toInt() + 1).toString())
        editor.apply()
        binding.btnLogin.setOnClickListener{
            editor.putString("account", binding.etAccount.toString().trim())
            editor.putString("password", binding.etPassword.toString().trim())
            editor.apply()
            Toast.makeText(this, "登录成功!", Toast.LENGTH_SHORT).show()
            val intent = Intent(this, MainActivity::class.java)
            startActivity(intent)
            finish()
        }
    }

4、增删改查

其实对数据表的增删改查逻辑在StudentDao中已经封装好了,我们在Activity里面也只是调用方法实现界面和数据库的交互罢了。具体的操作逻辑如下:

输入学号、姓名和年龄后点击添加可以添加学生;输入学号点击查询可以查询学生信息,然后点击删除会删除信息,点击修改会修改输入框中的学生信息,最后如果输入的学号不存在而且你点查询了,会显示所有学生的信息,如果存在只会显示该学生的信息。

    override fun onClick(p0: View?) {
        var stuId = binding.etId.text.toString()
        var stuName = binding.etName.text.toString()
        var stuAge = binding.etAge.text.toString()
        var stu = Student(stuId, stuName, stuAge)
        var flag = (studentDao.queryById(stuId) != null)
        when(p0?.id) {
            R.id.btn_insert->{
                if (flag) {
                    Toast.makeText(this, "学生已存在,无法添加", Toast.LENGTH_SHORT).show()
                } else {
                    studentDao.insertStudent(stu)
                    Toast.makeText(this, "添加成功!", Toast.LENGTH_SHORT).show()
                }
            }
            R.id.btn_delete->{
                if (flag) {
                    studentDao.deleteStudent(stu)
                    Toast.makeText(this, "删除成功!", Toast.LENGTH_SHORT).show()
                } else {
                    Toast.makeText(this, "该学生不存在,无法删除", Toast.LENGTH_SHORT).show()
                }
            }
            R.id.btn_update->{
                if (flag) {
                    studentDao.updateStudent(stu)
                    Toast.makeText(this, "修改成功!", Toast.LENGTH_SHORT).show()
                } else {
                    Toast.makeText(this, "该学生不存在,无法修改", Toast.LENGTH_SHORT).show()
                }
            }
            R.id.btn_query->{
                if (flag) {// 如果存在则补全信息
                    binding.etAge.setText(studentDao.queryById(stuId)?.age)
                    binding.etName.setText(studentDao.queryById(stuId)?.name)
                    Toast.makeText(this, "查询到该学生信息", Toast.LENGTH_SHORT).show()
                } else {// 不存在则显示所有学生信息
                    studentList = studentDao.queryAllStudent()
                    adapter = StudentAdapter(this, R.layout.item_student, studentList)
                    binding.lvStu.adapter = adapter
                    Toast.makeText(this, "查询所有学生信息", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }

三、运行演示

1、首先进入登录界面,输入账号和密码然后点击登录即可,右上角是使用次数。

2、进入主界面,我们输入学号、姓名和年龄进行添加学生。


3、点击添加按钮,添加成功。再依次添加几个学生。

4、点击查询,此时学号是不存在的,所以就查询了所有学生的信息。


5、我们输入学号4,然后点击查询,可以看到查询到信息并自动补全了。


6、修改姓名和年龄,然后再点修改,再点击查询,发现已经修改好了信息。


7、我们再查询小益的信息,然后删除小益的信息。

四、实验总结

其实学生系统涉及到数据库的操作完全和前面的其他系统相似,真正做起来还是比较繁琐的。哪里有什么容易代码,都是在一个个bug解决中完成的。理论引导实战,光理论只会纸上谈兵,光实践缺少方法论,基础打牢了才能进阶,不然上限不会高,基础决定了你的上限。

五、源码下载

🔥源代码已上传CSDN,点击下载源代码🔥

🚀这有你错过的精彩内容🚀
Android Studio实现考试管理系统
Android Studio实现购物商城
Android Studio实现选课系统
Android Studio实现图书管理系统
Android Stduio实现外卖订餐系统

有关Kotlin实现简单的学生信息管理系统的更多相关文章

  1. ruby - i18n Assets 管理/翻译 UI - 2

    我正在使用i18n从头开始​​构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在ruby​​onrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi

  2. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  3. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  4. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  5. ruby - 简单获取法拉第超时 - 2

    有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url

  6. ruby-on-rails - 获取 inf-ruby 以使用 ruby​​ 版本管理器 (rvm) - 2

    我安装了ruby​​版本管理器,并将RVM安装的ruby​​实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby​​。有没有办法让emacs像shell一样尊重ruby​​的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el

  7. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  8. ruby-on-rails - 简单的 Ruby on Rails 问题——如何将评论附加到用户和文章? - 2

    我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。

  9. ruby-on-rails - 事件管理员日期过滤器日期格式自定义 - 2

    是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s

  10. ruby - 使用 Ruby 通过 Outlook 发送消息的最简单方法是什么? - 2

    我的工作要求我为某些测试自动生成电子邮件。我一直在四处寻找,但未能找到可以快速实现的合理解决方案。它需要在outlook而不是其他邮件服务器中,因为我们有一些奇怪的身份验证规则,我们需要保存草稿而不是仅仅发送邮件的选项。显然win32ole可以做到这一点,但我找不到任何相当简单的例子。 最佳答案 假设存储了Outlook凭据并且您设置为自动登录到Outlook,WIN32OLE可以很好地完成此操作:require'win32ole'outlook=WIN32OLE.new('Outlook.Application')message=

随机推荐