SQLite/Android Room是适合我的应用的数据库吗?

kuhbmx9i  于 2023-05-18  发布在  SQLite
关注(0)|答案(2)|浏览(197)

我正在构建一个应用程序,用户将控制一些滑块,根据这些滑块产生输出,然后输出将被保存,以便他们可以滚动浏览历史记录。滑块将被标记有分配的信息和属性,滑块的输出将被程序化地生成(除了一些预编码的示例)。因此,例如,如果三个滑块是“红色”、“绿色”和“蓝色”,则一直滑动红色和绿色滑块将输出“黄色”,然后“黄色”将与当前日期和时间一起保存在用户的历史记录中。所有这些都将在设备上完成,没有来自或去往服务器的任何内容。
在数据管理端,这看起来像是三个数据库,每个数据库都与其他数据库有多对多的关系。即,每个滑块将附接到多个输出,并且每个输出可以附接到多个滑块;然后,尽管每个时间戳将仅被附加到一个输出,但是每个输出可以被附加到多个时间戳。
为了实现这一点,我认为我需要使用SQLite + Room进行数据管理。我设想一个表用于滑块,第二个表用于输出,第三个表用于用户的历史,再加上用于滑块到输出和输出到历史的连接表。
我唯一的编程经验是业余爱好者级别的Web开发,所以Kotlin,SQLite,Room,关系数据库和Android开发对我来说都是新的。我只是想弄清楚我需要学习什么工具来构建这个,这样我就不会花费几周的时间来学习我甚至没有使用正确的工具来完成这项工作。我不知道我不知道什么,所以任何帮助都很感激。

wooyq4lh

wooyq4lh1#

SQLite/Android Room是适合我的应用的数据库吗?
简而言之,是的。
所有这些都将在设备上完成,没有来自或去往服务器的任何内容。
那么SQLite/Room将是合适的,因为每个设备都有自己的数据库。
在数据管理端,这看起来像是三个数据库,每个数据库都与其他数据库有多对多的关系。
只需要一个数据库,可能只有一个表,不需要关系。
我不知道我不知道什么,所以任何帮助都很感激。
也许可以考虑下面的工作演示,它似乎可以沿着您的需要做一些事情:

  • 显示3个滑块
  • 有一个保存按钮,将保存当前的滑块设置(大致)
  • 可在编辑文本中输入类型以保存描述和值
  • 输入时间的时间戳(最小到一秒而不是一毫秒)
  • 显示已保存滑块的列表
  • 如果单击列表中的项目,则滑块将根据保存的值进行更改

所以首先@Entity注解类(表)SliderHiistory:-

@Entity
data class SliderHistory(
    @PrimaryKey
    var sliderHistoryId: Long?=null,
    var sliderTimestamp: Long= System.currentTimeMillis() / 1000,
    var sliderDescription: String,
    var sliderRed: Float,
    var sliderGreen: Float,
    var sliderBlue: Float
)
  • 每个var将是表中的一列(值)。
    *sliderHistoryId列是一个特殊的列,因此,它唯一标识行(第一行为1,下一行可能为2,依此类推)。如果不提供该值,则将由SQLite生成。
  • 这是一个特殊的值,将是rowid的别名,这可能是最好的解释https://www.sqlite.org/autoinc.html
    *sliderTimestamp列将存储示例创建时的时间戳(日期/时间)(除非通过指定值覆盖,否则不会被覆盖)
    *sliderDescription允许保存描述,这可能对最终用户有用。
    *sliderRedSliderGreenSliderBlue将保留3个值。

要访问数据(插入和提取),请使用@Dao注解接口SliderHistoryDao

@Dao
interface SliderHistoryDao {
    @Insert
    fun insert(sliderHistory: SliderHistory): Long
    @Query("SELECT * FROM sliderHistory WHERE sliderHistoryId=:id")
    fun getSliderSettingsFromHistory(id: Long): SliderHistory
}
  • 一个函数插入数据,一个函数根据id提取单行作为SliderHistory对象。

要将上述内容结合在一起,请使用@Database注解的抽象类SliderDatabase:-

@Database(entities = [SliderHistory::class], exportSchema = false, version = 1)
abstract class SliderDatabase: RoomDatabase() {
    abstract fun getSliderHistoryDao(): SliderHistoryDao

    companion object {
        private var instance: SliderDatabase?=null
        fun getInstance(context: Context): SliderDatabase {
            if (instance==null) {
                instance = Room.databaseBuilder(context,SliderDatabase::class.java,"slider.db")
                    .allowMainThreadQueries()
                    .build()
            }
            return instance as SliderDatabase
        }
    }
}
  • 数据库将保存在默认文件夹(data/data/<the_package_name>/databases)中名为slider.db的文件中。请注意,为了方便和简洁,演示在主线程上运行(不建议已发布的App在主线程上访问数据库)。

伴随对象中的函数getInstance使用了所谓的单例,因此整个过程中只检索数据库类的单个示例。
ActivityMainActivity使用布局activity_main,该布局定义了3个滑块、用于描述的EditText、用于保存数据的Button以及用于显示存储数据的ListView:-

?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />

    <com.google.android.material.slider.Slider
        android:contentDescription="Red"
        android:id="@+id/red_slider"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >
    </com.google.android.material.slider.Slider>
    <com.google.android.material.slider.Slider
        android:contentDescription="Green"
        android:id="@+id/green_slider"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >
    </com.google.android.material.slider.Slider>

    <com.google.android.material.slider.Slider
        android:contentDescription="Blue"
        android:id="@+id/blue_slider"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >
    </com.google.android.material.slider.Slider>

    <EditText
        android:id="@+id/save_Description"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >
    </EditText>

    <Button
        android:id="@+id/save_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="SAVE"
        >
    </Button>

    <ListView
        android:id="@+id/history_listview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/teal_200"
        >
    </ListView>

</LinearLayout>

最后,Main_Activity将所有内容联系在一起:-

class MainActivity : AppCompatActivity() {

    /* UI variables to be set when the activity is started */
    lateinit var sliderRed: Slider
    lateinit var sliderGreen: Slider
    lateinit var sliderBlue: Slider
    lateinit var butonSave: Button
    lateinit var editTextSaveDescription: EditText
    lateinit var listviewHistory: ListView
    /* These will be reset */
    var adapter: SimpleCursorAdapter?=null
    var csr: Cursor?=null

    /* The database/room variables */
    lateinit var db: SliderDatabase /* an instance of the SliderDatabase */
    lateinit var dao: SliderHistoryDao /* for accessing the DAO functions */

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        /* set up the UI variables */
        sliderRed = this.findViewById(R.id.red_slider)
        sliderGreen = this.findViewById(R.id.green_slider)
        sliderBlue = this.findViewById(R.id.blue_slider)
        butonSave = this.findViewById(R.id.save_button)
        editTextSaveDescription = this.findViewById(R.id.save_Description)
        listviewHistory = this.findViewById(R.id.history_listview)

        /* Prepare to use the database */
        db = SliderDatabase.getInstance(this)
        dao = db.getSliderHistoryDao()

        /* setup the Save button on click listener */
        setUpSaveButton()
        /* setup the ListView */
        setOrRefreshHistoryList()
    }

    /* Function to prepare the Save button so it saves the current settings when clicked */
    fun setUpSaveButton() {
        butonSave.setOnClickListener {
            dao.insert(
                SliderHistory(
                    sliderRed = sliderRed.value,
                    sliderGreen = sliderGreen.value,
                    sliderBlue = sliderBlue.value,
                    sliderDescription = editTextSaveDescription.text.toString()
                )
            )
            setOrRefreshHistoryList()
        }
    }

    /* Function to prepare (first invocation) or refresh the ListView
        display data, if any, and setting the onItemClickListener so that
        if an item in the ListView is clicked it gets the stored values and
        applies them to the slider
    * */
    fun setOrRefreshHistoryList() {
        /* first get the latest data */
        /* Note as a Cursor adapter is used, a query is used as opposed to retrieving SliderHistoryObjetcs
            A CursorAdapter is very simple to implement, it being designed to work with Cursors
         */
        csr = db.getOpenHelper().writableDatabase.query("SELECT *,sliderhistoryId AS ${BaseColumns._ID}, sliderRed||':'||sliderGreen||':'||sliderBlue AS sliderValues FROM sliderhistory")
        if (adapter==null) {
            adapter = SimpleCursorAdapter(
                this,
                android.R.layout.simple_list_item_2,
                csr,
                arrayOf("sliderValues","sliderDescription"),
                intArrayOf(android.R.id.text1,android.R.id.text2),
                0
            )
            listviewHistory.adapter = adapter

            /* setup the onItemClickListener */
            listviewHistory.setOnItemClickListener { parent, view, position, id ->
                val sh = this.dao.getSliderSettingsFromHistory(id)
                sliderRed.value = sh.sliderRed
                sliderGreen.value = sh.sliderGreen
                sliderBlue.value = sh.sliderBlue
            }
        } else {
            adapter!!.swapCursor(csr)
        }
    }
}

结果

最初运行时:-

  • 在此阶段,数据库为空(尽管由于尝试提取数据而创建)。

如果在编辑文本中输入了黑色(或任何内容),并单击了保存按钮,则:-

即插入的行现在被显示。
现在如果

  • 红色滑块一直向右移动,红色输入编辑文本,单击保存,然后
  • 只有绿色滑块一直向右,绿色进入编辑文本并单击保存,然后
  • 蓝色也是如此,然后
  • 所有三个滑块都被移动,然后输入白色:-

现在,如果在列表中单击黑色:-

点击红色:-

等等(当然,中间值将被同样地保存,即,每次都保存所有三个值)。
现在,如果你想提取日期和时间,并让它显示在ListView中,而不是组合的颜色值,然后更改行:

csr = db.getOpenHelper().writableDatabase.query("SELECT *,sliderhistoryId AS ${BaseColumns._ID}, sliderRed||':'||sliderGreen||':'||sliderBlue AS sliderValues FROM sliderhistory")

csr = db.getOpenHelper().writableDatabase.query("SELECT *,sliderhistoryId as ${BaseColumns._ID}, datetime(sliderTimestamp,'unixepoch') AS sliderValues FROM sliderhistory")

将促进这一点,例如:

其他

以下细微的变化使加载的颜色能够被看到,并且还引入了第四个颜色元素(透明度)。
首先,将TextView添加到布局中:

<TextView
    android:id="@+id/swatch"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text=""
    >
</TextView>

(在3个滑块之后(你可能想要第四个))
然后是一个新的函数(对于演示,包含为MainActivity中的函数):-

fun convertRGandBtoInt(red: Int, green: Int, blue: Int): Int {
    return (red * 65536) + (green * 256) + blue
}
  • 这位于最后两个花括号}之间

然后在行(在onItemClickListener中)sliderBlue.value = sh.sliderBlue之后添加了以下行:

val bg = convertRGandBtoInt((sh.sliderRed * 255F).toInt(), (sh.sliderGreen * 255F).toInt(), (sh.sliderBlue * 255F).toInt())
            listviewHistory.setBackgroundColor(bg + (128 * 65536 * 256)) /* 50 % transparent */
            colourSwatch.setBackgroundColor(bg + (255 * 65536 * 256)) /* solid */
  • 第一个改变了ListView的背景颜色BUT,使其半透明(这样你就可以看到项目),因此它不是真实的的颜色。
  • 第二个改变了TextView的颜色,但这次没有透明度,所以是实际的颜色。

有了这个和黑色,红色,绿色,蓝色和白色保存,然后点击不仅设置滑块,但也改变了颜色,例如。

黑色

红色

绿色

等等

ecfsfe2w

ecfsfe2w2#

我建议使用ROOM,因为它更容易实现,并且带有更少的样板代码(Docs
另外,我看不出你为什么需要三张table。我想你的情况一张table就够了。只需将时间戳、用户和颜色存储在一个表中,并使用时间戳(加上用户)作为主键。

相关问题