Android实现永久存储数据的三种方式

Android实现永久存储数据的三种方式(Kotlin实现)

1.通过文件的方式

1.1 适用范围

一些简单的文本数据

1.2 简单实例

作用:实现文本框可以在重新启动之后仍然保留上一次推出时候的数据

1.2.1 布局代码

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/editText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="请输入"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

其中较难懂的参数为ems 表示为控件的字符串长度,超出部分将不再进行显示

1.2.2 Activity代码

package com.example.csdnsqlite

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import kotlinx.android.synthetic.main.activity_main.*
import java.io.*
import java.lang.StringBuilder
import kotlin.math.log

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val text=load()
        editText.setText(text)
        editText.setSelection(text.length)
    }

    override fun onDestroy() {
        //在每次活动结束时候 将文本进行存储
        super.onDestroy()
        val text=editText.text.toString()
        save(text)
    }

    private fun save(Text:String){
        try {
            val output=openFileOutput("data", Context.MODE_PRIVATE)
            val writer=BufferedWriter(OutputStreamWriter(output))
//            writer.use { // use当写入完成之后,可以自动关闭流,不用再手动关闭
//                it.write(Text)
//            }
            writer.write(Text) //这种方法需要自己手动关闭 注意关闭的顺序与开启的顺序刚好相反
            writer.close()
            output.close()
        }catch (e:IOException){
            e.printStackTrace()
        }
    }

    private fun load():String{
        val text=StringBuilder()
        try {
            val input=openFileInput("data")
            val reader=BufferedReader(InputStreamReader(input))
//            reader.use { //无需手动关闭 
//                reader.forEachLine {
//                    text.append(it)
//                }
//            }
            reader.forEachLine { //与上面相同 这种方式需要手动进行关闭
                text.append(it)
            }
            reader.close()
            input.close()
        }catch (e:IOException){
            e.printStackTrace()
        }
        return text.toString()
    }
}

首先获得文件的输出流,通过Context中的openFileOutput函数
openFileOutput接受两个参数
第一个:文件名称
也就是你存储的那个文件叫什么名字
第二个:关于写入方式的参数,有两个
MODE_PRIVATE表示若出现同名文件,则会进行覆盖;MODE_APPEND表示若出现同名文件,则继续往里面添加
之后根据获取的FileoutputStream对象,通过java流的方式写入文件
获取一个BufferedWriter对象,可以通过这个对象对文件进行写入
方法:BufferedWriter(OutputStreamWriter(刚获得的FileoutputStream))

要获得文件的输入流,通过刚刚类似的openFileInput
openFileOutput接受一个参数:
文件名称,就是你刚刚存储的那个文件的名称,至于为什么不需要路径,那是因为android这些文件都有固定的路径,只需要文件名称就可以唯一确定文件
根据获取的FileinputStream对象,可以对文件内容进行读取
方法:BufferedReader(InputStreamReader(刚获得的FileinputStream))

运行时:
在这里插入图片描述

2.通过sharedpreferences来进行存储

2.1适用范围

这种方式是通过键值对的方式来进行存储,常见的使用情况,有存储用户的偏好设置等情况

2.2 简单实例

一个可输入文本框,下面两个按钮,一个用来存储数据,一个用来读取数据

2.2.1 布局代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/editText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:ems="10"
        android:hint="请输入"
        android:inputType="textPersonName"
        android:textSize="24sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/buttonSave"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="save"
        app:layout_constraintEnd_toStartOf="@+id/buttonLoad"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/buttonLoad" />

    <Button
        android:id="@+id/buttonLoad"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:text="Load"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/buttonSave"
        app:layout_constraintTop_toBottomOf="@+id/editText" />
</androidx.constraintlayout.widget.ConstraintLayout>

该布局主要是通过constraintlayout来完成的,其实大部分在图形化界面中完成的。。。。这种代码说实话有点难看懂,总之有一个文本输入框和两个按钮就可了。

2.2.2 Activity代码
package com.example.csdnsharedpreferences

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        buttonSave.setOnClickListener {
            val text=editText.text.toString()
            val editor=getSharedPreferences("data",0).edit()
            editor.putString("text",text)
            editor.apply()
        }
        buttonLoad.setOnClickListener {
            val prefs=getSharedPreferences("data", Context.MODE_PRIVATE)
            val text=prefs.getString("text","")
            editText.setText(text)
            if (text != null) {
                editText.setSelection(text.length)
            }
        }
    }
}

写入:

  1. 通过getSharedPreferences的edit获取一个SharedPreferences.Editor!对象
    getSharedPreferences接受两个参数:
    第一个: 文件名称
    也就是你存储的那个文件叫什么,这种方式是通过xml的文件格式来进行存储的
    第二个:操作模式
    目前只有Context.MODE_PRIVATE也就是0,其余的几种模式在Android发展过程中都被废弃了。。。

  2. 之后通过putString,putInt等一系列put方法往里面添加数据
    添加格式为 key:value格式 ,两个参数一个为键,一个为值

  3. 添加完之后,一定要进行apply进行保存更改

读取:

  1. 通过getSharedPreferences获取一个SharedPreferences对象,参数与写入时候相同

  2. 根据获得的对象 调用getString,getInt等函数,获取所需要的数据
    参数一般为两个:
    第一个:键 第二个:没有找见的时候的默认值

2.2.3 运行效果

在这里插入图片描述

3.通过SQLite数据库来进行存储

3.1使用情况

在面对一些复杂的数据的时候,前面两种方式就显得比较老土了,肯定无法胜任,这就需要数据库出马了,android本身是内置数据库的,短小而精悍的SQLite数据库成为了不二之选。

3.2简单示例

3.2.1讲解

android为了方便进行数据库的管理,提供了一个名为SQLiteOpenHelper的类,来帮助我们,不过不能直接用,这个类是个抽象类,当我们想使用的时候,必须用自己的类去继承这个类,主要实现两个抽象的方法:onCreate和onUpdate,看看名字也能猜出来,一个是创建的时候进行调用,另一个是当数据库升级的时候进行调用。

SQLiteOpenHelper可以通过getReadableDatabase和getWritableDatabase来打开的数据库,不存在则创建,区别在于前一种方法当数据库无法写入的时候,例如存储空间满了的时候,会以只读的方式打开,而后者则会报错。

就不写布局文件了,就是一些简单的按钮,直接看Activity等文件吧

3.2.2 创建数据库

创建一个数据库,用于记录学生的信息,简单起见,就姓名,年龄,性别,学号吧。
如果学过SQL,创建表的话,应该这么写

CREATE TABLE Student(
id integer primary key autoincrement,
name text ,
age integer,
sex boolean,
stuNo text)

新建一个文件StudentDatabaseHelper来完成创建表的操作

package com.example.csdndatabase

import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import android.widget.Toast

class StudentDatabaseHelper(val context: Context,name :String,version :Int):
    SQLiteOpenHelper(context,name,null,version) {
    private val createTable= "CREATE TABLE Student(\n" +
            "id integer primary key autoincrement,\n" +
            "name text ,\n" +
            "age integer,\n" +
            "sex boolean,\n" +
            "stuNo text)"
    
    override fun onCreate(db: SQLiteDatabase?) {
        db?.execSQL(createTable)
        Toast.makeText(context,"create",Toast.LENGTH_SHORT).show()
    }

    override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
    }
}

SQLiteOpenHelper接受四个参数
1.上下文对象,为了保证可以对数据库进行操作
2.数据库的名称
3.cursor一般情况下为null,查询时候会返回这么一个对象,里面有我们所查询到的信息
4.数据库的版本,为整型

MainActivity代码

package com.example.csdndatabase

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val dbHelper=StudentDatabaseHelper(this,"StuData.db",1)
        buttonCreateDatabase.setOnClickListener {
            dbHelper.writableDatabase //实际上调用了getWritableDatabase
        }
    }
}

再调用getWritableDatabase,因为没有创建数据库,会在调用时,自动创建数据库。

运行时:
在这里插入图片描述
可以看到,第一次点击的时候创建了数据库,之后再点击,没有响应,那是因为只有第一次才会调用oncreate函数,之后发现已经创建成功了,就不会再进行调用了。

怎么确定创建了数据库呢?
点击右下角的Device Explorer(根据版本的不同,你的可能不在那里,但是稍微找找,,应该很好找见)
之后按以下步骤就可以找见数据库了,在com.example.你的项目名称处进行寻找。里面有一个你创建的db文件,另一个则是生成的日志文件。
在这里插入图片描述
想看一下数据库里面的内容?
需下载DB Browser
选择File–Settings–Plugins 输入DB Browser 就可以下载安装了
找不见这个工具的话,ctrl+shift+A 输入DB Browser进行搜索

笔者用着这小程序有点问题 又下载了个sqlitebrowser
认识中国字 稍微看看 应该就会用了
打开后的内容如下:
在这里插入图片描述
数据库的基本操作是增删查改~ 接下来 对表进行插入
插入操作:
更改一下布局,在下面再增加一个按钮,用于添加数据
对MainActivity进行更改,在oncreate中添加如下代码:

 buttonAddData.setOnClickListener {
            val db=dbHelper.writableDatabase
            val values=ContentValues().apply {
                put("name","小明")
                put("age",18)
                put("sex",true)
                put("stuNo","123456")
            }
            db.insert("Student",null,values) //插入数据
        }

首先获取数据库对象,之后创建一个值,不用传入id,因为id会自动创建
最后进行插入
查看数据库内容,可以看出添加了几条数据:
在这里插入图片描述

更新操作:
继续增加按钮
MainActivity增加的代码如下:

        buttonUpdate.setOnClickListener {
            val db=dbHelper.writableDatabase
            val values=ContentValues()
            values.put("age",22)
            db.update("Student",values,"name=?", arrayOf("小明"))
        }

该代码将名字等于小明的年龄都改为了22
较难理解的是update的参数,共有四个:
第一个:
要进行改的表名
第二个:
你自己创建的ContentValues,其中包含要更改的信息
第三和第四个:
共同构成筛选条件,确定哪些行需要进行更改
更改后的数据如下:
在这里插入图片描述
删除操作
例如需要删除id=3的那行
先在布局中继续添加按钮
在MainActivity中添加代码:

        buttonDelete.setOnClickListener {
            val  db=dbHelper.writableDatabase
            db.delete("Student","id==?", arrayOf("3"))
        }

delete 第一个参数为表名,后两个决定删除的条件
删除数据后的结果如下:
在这里插入图片描述
查找操作:
查找操作较为复杂,通过query函数进行实现,其中包括七个参数

参数对应的SQL语句
tablefrom table_name
columnsselect column1,column2
selectionwhere column=value
selectionArgs就是上面的value
groupBygroup by column
havinghaving column=value
orderByorder by column1,column2

举一个较为简单的例子,查询所有数据,查询数据的时候,要将查询到的数据放在一个cursor中,之后进行读取。
现在界面中再增加一个按钮,MainActivity增加如下的代码:

        buttonSelect.setOnClickListener {
            val db=dbHelper.writableDatabase
            val cursor=db.query("Student",null,null,
                null,null,null,null)
            if (cursor.moveToFirst()){
                do {
                    val name=cursor.getString(cursor.getColumnIndex("name"))
                    val age=cursor.getInt(cursor.getColumnIndex("age"))
                    val StuNo=cursor.getString(cursor.getColumnIndex("stuNo"))
                    Log.d("MainActivity","$name is $age years old ,StuNo is $StuNo")
                }while (cursor.moveToNext())
            }
        }

一共有三条数据,可以看到打印的结果如下:
在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要实现Android 9上永久性开启ADB的Root权限,可以按照以下步骤进行操作: 首先,确保手机已经成功Root,并且安装了Root管理器应用程序,例如SuperSU或Magisk Manager。 接下来,打开Root管理器应用程序,进入设置界面。 在设置界面中,查找并选择"ADB"或"开发者选项"选项。 在"ADB"或"开发者选项"下,查找"ADB以root方式运行"或类似的选项。 启用"ADB以root方式运行"选项。这将允许通过ADB以Root权限访问设备。 保存设置并退出Root管理器应用程序。 重新启动设备,并确保已成功启动。 通过USB连接手机和计算机。 在计算机上打开命令提示符或终端。 运行以下命令以确认手机已成功连接: adb devices 如果设备成功连接,将显示设备的序列号。 现在,可以使用ADB命令以Root权限访问设备。例如,可以运行以下命令来获取设备的Root权限: adb shell 以上就是在Android 9上实现永久性开启ADB的Root权限的步骤。请注意,Root权限可能会对设备的安全性和稳定性产生一定影响,请谨慎操作,并仔细评估Root所带来的风险和利益。 ### 回答2: 在Android 9中,实现永久开启ADB的root权限可以采取以下步骤: 首先,确保已经成功获取了Root权限,并且已经安装了ADB驱动程序。 1. 使用Root浏览器或类似的文件管理器,前往/system目录下的文件夹,并找到名为build.prop的文件,将其复制到外部存储中备份一份。 2. 使用任意文本编辑器打开build.prop文件,在文件末尾添加以下代码:adb.tcp.port=5555 3. 保存并退出文本编辑器,将修改后的build.prop文件替换回/system目录中的原文件。在替换文件时,请确保将文件权限设置为'r-w-r-r'(即644)。 4. 打开终端或命令提示符窗口,通过ADB连接到您的Android设备,输入以下命令: adb shell su -c "setprop service.adb.tcp.port 5555" 以上命令将设置ADB的TCP端口为5555。 5. 在终端或命令提示符窗口中,再次输入以下命令: adb tcpip 5555 此命令将启用ADB的TCP/IP功能,并将端口设置为5555。 6. 断开设备与计算机之间的USB连接,并在设备上找到其IP地址。 7. 最后,在终端或命令提示符窗口中,输入以下命令: adb connect 设备IP地址:5555 这个命令将通过TCP/IP连接至设备。 现在,您的Android设备将永久开启ADB的root权限,并通过TCP/IP连接与计算机通信。您可以使用命令行工具或ADB进行文件传输、调试和其他操作。 请注意,此方法需要Root权限,操作时需要小心谨慎,确保您了解自己的操作,并对设备进行备份以防止意外损坏。 ### 回答3: 在Android 9中实现永久性开启ADB的root权限可以通过以下步骤: 1. 首先,确保您的设备已经处于Root状态。Root是指获取Android设备管理员权限的过程。请注意,Root设备可能会违反设备制造商的保修政策,并增加安全风险。在进行Root之前,请确保了解所有潜在的风险和后果。 2. 安装ADB驱动程序并将其设置为设备管理器。ADB是Android Debug Bridge的缩写,它允许您通过USB调试模式与Android设备进行通信。 3. 连接您的设备到计算机上,并打开命令提示符或终端窗口。 4. 输入命令"adb root",以获取ADB的Root权限。此命令将设备切换到Root Shell状态。 5. 输入命令"adb remount",以将设备的文件系统重新挂载为可读写模式。这样做是为了能够对设备进行修改。 6. 输入命令"adb disable-verity",以禁用设备的verity验证。verity验证是一种安全特性,用于检查系统文件是否已被修改。 7. 输入命令"adb reboot",以重新启动您的设备。 8. 这样,您的设备将具有永久性开启ADB的Root权限。 请注意,这些步骤仅适用于Root过的设备,并且可能因设备型号和制造商而有所不同。在执行任何操作之前,请务必备份您的设备数据,并谨慎采取措施,以免损坏您的设备。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值