android开发,使用kotlin学习数据存储

简介: android开发,使用kotlin学习数据存储



1、文件存储

文件存储是Android中最基本的数据存储方式,它不对存储的内容进行任何格式化处理,有数据都是原封不动地保存在文件当中的,因此它比较适合存储一些简单的文本数据或者二进制数据。

(1)将数据存储在文件中

Context类中提供了一个openFileOutput()方法,用于将数据存储到指定的文件中。

第一个参数:文件名(系统会自动创建这个文件)。

第二个参数:文件的操作模式

文件的操作模式有以下几种:

  • Context.MODE_PRIVATE:私有覆盖模式。只能被当前应用访问,并且如果写入,则覆盖。
  • Context.MODE_APPEND:私有追加模式。只能被当前应用访问,并且如果写入,则追加。
  • Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE已在Android4.2版本中被废除。

具体实现:

private fun save(inputText: String) {
            try {
                val output=openFileOutput("data", Context.MODE_PRIVATE)
                val writer=BufferedWriter(OutputStreamWriter(output))
                //这里使用了kotlin的内置函数use,它会保证在Lambda
                //表达式中的代码全部执行完之后自动将外层的流关闭,这
                //样就不再需要我们写一个finally语句,手动关闭流。
                writer.use {
                    it.write(inputText)
                }
                Toast.makeText(this,inputText,Toast.LENGTH_SHORT).show()
            }catch (e:IOException){
                e.printStackTrace()
            }
    }

如何证实数据是否已经保存成功了呢?

使用快捷键Ctrl+Shift+A(Mac系统是command+shift+A)打开搜索功能,在搜索框输入“Device File Explorer”即可找到这个工具,我们在这工具里找到/data/data/com.example.filepersistencetest/files/目录,里面有一个生成的data文件,双击打开,查看里面的内容。

(2) 从文件中读取数据

Context类提供的openFileinput()方法,用于从文件中读取数据。

参数:文件名

具体实现:

private fun load():String{
        val content=StringBuilder()
        try {
            val input=openFileInput("data")
            val reader=BufferedReader(InputStreamReader(input))
            //kotlin提供的内置扩展函数forEachLine,它会将读到的内容都回调到Lambda表达式中。
            reader.use {
                reader.forEachLine {
                    content.append(it)
                }
            }
        }catch(e:IOException){
            e.printStackTrace()
        }
        return content.toString()
    }

(3)实战演练:重新启动程序时EditText中能保留我们上次输入的内容。、

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val  inputText=load()
        if(inputText.isNotEmpty()){
            val editText:EditText=findViewById(R.id.editText)
            editText.setText(inputText)
            editText.setSelection(inputText.length)
        }
    }
    override fun onDestroy() {
        super.onDestroy()
        val editText:EditText=findViewById(R.id.editText)
        val inputText=editText.text.toString()
        save(inputText)
    }
    private fun save(inputText: String) {
            try {
                val output=openFileOutput("data", Context.MODE_PRIVATE)
                val writer=BufferedWriter(OutputStreamWriter(output))
                writer.use {
                    it.write(inputText)
                }
                Toast.makeText(this,inputText,Toast.LENGTH_SHORT).show()
            }catch (e:IOException){
                e.printStackTrace()
            }
    }
    private fun load():String{
        val content=StringBuilder()
        try {
            val input=openFileInput("data")
            val reader=BufferedReader(InputStreamReader(input))
            reader.use {
                reader.forEachLine {
                    content.append(it)
                }
            }
        }catch(e:IOException){
            e.printStackTrace()
        }
        return content.toString()
    }
}

2、SharedPreferences存储

不同于文件存储,SharedPreferences是使用键值对的方式来存储数据的。

Context类中的getSharedPreferences()方法,获取SharedPreferences对象。

第一个参数:指定SharedPreferences文件的名称。(如果指定文件的名称不存在就会创建一个,SharedPreferences文件都是存放在/data/data/<package name>/shared_prefs目录)。

第二个参数:指定操作模式。只有MODE_PRIVATE可选,MODE_PRIVATE:只有当前的应用程序才可以对这个SharedPreferences文件进行读写。

(1)将数据存储到SharedPreferences中

具体实现:

val editor=getSharedPreferences("data", Context.MODE_PRIVATE).edit()
            editor.putString("name","Tom")
            editor.putInt("age",28)
            editor.putBoolean("married",false)
            editor.apply()//提交

如何证实数据是否已经保存成功了呢?

使用快捷键Ctrl+Shift+A(Mac系统是command+shift+A)打开搜索功能,在搜索框输入“Device File Explorer”即可找到这个工具,我们在这工具里找到/data/data/com.example.sharedpreferencestest/shared_prefs/目录,里面有一个生成的data.xml文件,双击打开,查看里面的内容。

(2)从sharedpreferences中读取数据

具体实现

val prefs=getSharedPreferences("data",Context.MODE_PRIVATE)
            val name=prefs.getString("name","")
            val age=prefs.getInt("age",0)
            val married=prefs.getBoolean("married",false)
            Log.d("MainActivity","name is $name")
            Log.d("MainActivity","age is $age")
            Log.d("MainActivity","married is $married")

3、SQLite数据库存储

(1)创建数据库

SQLiteOpenHelper类是一个抽象类,有两个抽象方法,onCreate()和onUpgrade()。

  • onCreate(SQLiteDatabase):在数据第一次生成的时候会调用这个方法,也就是说,只有创建数据库的时候才会调用,还可以在这个方法里生成数据库表。
  • onUpgrade(SQLiteDatabase,int,int):当数据库需要升级的时候,Android系统会自动调用这个方法,一般在这个方法里删除数据表,并建立新的数据表。

SQLiteOpenHelper类的构造方法:

第一个参数:Context

第二个参数:数据库名

第三个参数:运行我们在查询数据时放回一个自定义的Cursor,一般传入null即可

第四个参数:表明当前数据库的版本号

步骤

定义SQLiteOpenHelper的子类,在该类中创建一个名为BookStore.db的数据库

class MyDatabaseHelper(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)"
    private val createCategory = "create table Category(" +
            "id integer primary key autoincrement," +
            "category_name text," +
             "category_code integer)"
    override fun onCreate(p0: SQLiteDatabase?) {
        if (p0 != null) {
            p0.execSQL(createBook)
            p0.execSQL(createCategory)
        }
        Toast.makeText(context,"Create succeeded",Toast.LENGTH_SHORT).show()
    }
    override fun onUpgrade(p0: SQLiteDatabase?, p1: Int, p2: Int) {
        if (p0 != null) {
            p0.execSQL("drop table if exists Book")
            p0.execSQL("drop table if exists Category")
            onCreate(p0)
        }
    }
}

调用MyDatabaseHelper类完成表的创建

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val dbHelper=MyDatabaseHelper(this,"BookStore.db",1)
        dbHelper.writableDatabase
    }
}

(2)升级数据库

val dbHelper=MyDatabaseHelper(this,"BookStore.db",1)

改为

val dbHelper=MyDatabaseHelper(this,"BookStore.db",2)

表示数据库升级

(3)添加数据

insert():专门用于添加数据。

第一个参数:表名

第二个参数:用于在未指定添加数据的情况下给某些可为空的列自动赋值给NULL,一般用不到这个功能,传入null即可。

第三个参数:ContentValues对象

步骤

获取SQLiteDatabase对象

val dbHelper=MyDatabaseHelper(this,"BookStore.db",1)
val db=dbHelper.writableDatabase

使用ContentValues对要添加的数据进行组装

val values1=ContentValues().apply {
                put("name","The Da Vinci Code")
                put("author","Dan Brown")
                put("pages",454)
                put("price",16.96)
            }

调用insert()方法将数据添加到表中

db.insert("Book",null,values1)

(4)更新数据

updata():对数据进行更新。

参数:第一个参数:表名,指定更新哪张表的数据。

第二个参数:ContentValues对象,要把更新数据在这里组装进去。

第三、四个参数:用于约束更新某一行或某几行的数据,不指定的话默认会更新所有行

步骤

获取SQLiteDatabase对象

val dbHelper=MyDatabaseHelper(this,"BookStore.db",1)
val db=dbHelper.writableDatabase

构建ContentValues对象,并且给它指定一组数据,说明把价格这一系列的数据更新成10.99。

val values=ContentValues()
values.put("price",10.99)

调用SQLiteDatabase的updata()执行具体的更新操作。

db.update("Book",values,"name=?", arrayOf("The Da Vinci Code"))

(5)删除数据

delete()方法:专门用于删除数据。

第一个参数:表名

第二、三个参数:用于约束删除某一行或者某几行的数据,不指定的话会默认删除所有行

val dbHelper=MyDatabaseHelper(this,"BookStore.db",1)
val db=dbHelper.writableDatabase
db.delete("Book","pages>?", arrayOf("500"))

(6)查询数据

步骤

获取SQLiteDatabase对象

val dbHelper=MyDatabaseHelper(this,"BookStore.db",1)
val db=dbHelper.writableDatabase

调用query()方法后会返回一个Cursor对象,查询到的所有数据都可以从这个对象中取出。

val cursor=db.query("Book",null,null,null,null,null,null)
         //查询完后获得一个Cursor对象,接着我们调用它的moveToFirst()方法,
         //将数据的指针移动到第一行的位置,
         //然后进入一个循环当中,去遍历查询到的每一行数据
        if(cursor.moveToFirst()){
             do{
                    val name=cursor.getString(cursor.getColumnIndex("name"))
                    val author=cursor.getString(cursor.getColumnIndex("author"))
                    val pages=cursor.getInt(cursor.getColumnIndex("pages"))
                    val price=cursor.getDouble(cursor.getColumnIndex("price"))
                    Log.d("MainActivity","Book name is $name")
                    Log.d("MainActivity","Book author is $author")
                    Log.d("MainActivity","Book pages is $pages")
                    Log.d("MainActivity","Book price is $price")
              }while (cursor.moveToNext())
          }
          cursor.close()

4、使用SQL操作数据库

使用SQL来完成前面学过的CRUD操作。

添加数据:

db.execSQL("insert  into Book(name, author, pages, price)  values(?,?,?,?)",
array0f("The  Da  Vinci  Code","Dan  Brown","454","16.96")
)
db.execSQL("insert into Book(name, author, pages, price) values(?,?,?,?)",
array0f("The  Lost  Symbol","Dan  Brown","510","19.95")
)

更新数据:

db.execSQL("update Book set price=? where name=?",array0f("10.99","The Da Vinci Code"))

删除数据:

db.execSQL("delete  from Book where  pages>?",array0f("500"))

查询数据:

val cursor=db.rawQuery("select*from Book", null)

 

目录
相关文章
|
7天前
|
Linux 编译器 Android开发
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
在Linux环境下,本文指导如何交叉编译x265的so库以适应Android。首先,需安装cmake和下载android-ndk-r21e。接着,下载x265源码,修改crosscompile.cmake的编译器设置。配置x265源码,使用指定的NDK路径,并在配置界面修改相关选项。随后,修改编译规则,编译并安装x265,调整pc描述文件并更新PKG_CONFIG_PATH。最后,修改FFmpeg配置脚本启用x265支持,编译安装FFmpeg,将生成的so文件导入Android工程,调整gradle配置以确保顺利运行。
26 1
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
|
2天前
|
安全 数据处理 Android开发
构建高效Android应用:Kotlin协程的实践之路
【4月更文挑战第26天】 在面对现代Android开发时,性能优化和流畅的用户体验成为了开发者们追求的目标。Kotlin作为一种现代化的编程语言,通过其协程特性为Android应用带来了前所未有的并发处理能力。本文将深入探讨如何利用Kotlin协程提升Android应用的响应性和效率,同时保持代码的简洁性。我们将从协程的基础概念出发,逐步揭示如何在实际应用中运用这些强大的工具,以及它们如何改善应用架构和用户交互体验。
|
4天前
|
数据库 Android开发 开发者
安卓应用开发:构建高效用户界面的策略
【4月更文挑战第24天】 在竞争激烈的移动应用市场中,一个流畅且响应迅速的用户界面(UI)是吸引和保留用户的关键。针对安卓平台,开发者面临着多样化的设备和系统版本,这增加了构建高效UI的复杂性。本文将深入分析安卓平台上构建高效用户界面的最佳实践,包括布局优化、资源管理和绘制性能的考量,旨在为开发者提供实用的技术指南,帮助他们创建更流畅的用户体验。
|
4天前
|
移动开发 Java Android开发
构建高效Android应用:采用Kotlin协程优化网络请求
【4月更文挑战第24天】 在移动开发领域,尤其是对于Android平台而言,网络请求是一个不可或缺的功能。然而,随着用户对应用响应速度和稳定性要求的不断提高,传统的异步处理方式如回调地狱和RxJava已逐渐显示出局限性。本文将探讨如何利用Kotlin协程来简化异步代码,提升网络请求的效率和可读性。我们将深入分析协程的原理,并通过一个实际案例展示如何在Android应用中集成和优化网络请求。
|
4天前
|
调度 Android开发 开发者
构建高效Android应用:探究Kotlin协程的优势与实践
【4月更文挑战第24天】随着移动开发技术的不断演进,提升应用性能和用户体验已成为开发者的核心任务。在Android平台上,Kotlin语言凭借其简洁性和功能性成为主流选择之一。特别是Kotlin的协程功能,它为异步编程提供了一种轻量级的解决方案,使得处理并发任务更加高效和简洁。本文将深入探讨Kotlin协程在Android开发中的应用,通过实际案例分析协程如何优化应用性能,以及如何在项目中实现协程。
|
5天前
|
网络协议 Shell Android开发
Android 深入学习ADB调试原理(1)
Android 深入学习ADB调试原理(1)
20 1
|
10天前
|
移动开发 Android开发 开发者
构建高效Android应用:采用Kotlin进行内存优化的策略
【4月更文挑战第18天】 在移动开发领域,性能优化一直是开发者关注的焦点。特别是对于Android应用而言,由于设备和版本的多样性,确保应用流畅运行且占用资源少是一大挑战。本文将探讨使用Kotlin语言开发Android应用时,如何通过内存优化来提升应用性能。我们将从减少不必要的对象创建、合理使用数据结构、避免内存泄漏等方面入手,提供实用的代码示例和最佳实践,帮助开发者构建更加高效的Android应用。
|
21天前
|
移动开发 API Android开发
构建高效Android应用:探究Kotlin协程的优势与实践
【4月更文挑战第7天】 在移动开发领域,性能优化和应用响应性的提升一直是开发者追求的目标。近年来,Kotlin语言因其简洁性和功能性在Android社区中受到青睐,特别是其对协程(Coroutines)的支持,为编写异步代码和处理并发任务提供了一种更加优雅的解决方案。本文将探讨Kotlin协程在Android开发中的应用,揭示其在提高应用性能和简化代码结构方面的潜在优势,并展示如何在实际项目中实现和优化协程。
|
21天前
|
XML 开发工具 Android开发
构建高效的安卓应用:使用Jetpack Compose优化UI开发
【4月更文挑战第7天】 随着Android开发不断进化,开发者面临着提高应用性能与简化UI构建流程的双重挑战。本文将探讨如何使用Jetpack Compose这一现代UI工具包来优化安卓应用的开发流程,并提升用户界面的流畅性与一致性。通过介绍Jetpack Compose的核心概念、与传统方法的区别以及实际集成步骤,我们旨在提供一种高效且可靠的解决方案,以帮助开发者构建响应迅速且用户体验优良的安卓应用。
|
23天前
|
监控 算法 Android开发
安卓应用开发:打造高效启动流程
【4月更文挑战第5天】 在移动应用的世界中,用户的第一印象至关重要。特别是对于安卓应用而言,启动时间是用户体验的关键指标之一。本文将深入探讨如何优化安卓应用的启动流程,从而减少启动时间,提升用户满意度。我们将从分析应用启动流程的各个阶段入手,提出一系列实用的技术策略,包括代码层面的优化、资源加载的管理以及异步初始化等,帮助开发者构建快速响应的安卓应用。