【问题标题】:Kotlin - SQLiteDatabase - Unsure how to get column text to show in ViewHolderKotlin - SQLiteDatabase - 不确定如何让列文本显示在 ViewHolder 中
【发布时间】:2021-09-03 07:43:08
【问题描述】:

这是我第一次发帖。我做了一个简单的计数应用程序。我可以连接并将数据添加到数据库,但我只是不知道如何查看 COLUMN_COUNT 字段中的数据。我创建了一个 retrieveCount 函数,但无法弄清楚如何在 HistoryAdapter 页面上调用它而不出错。

我已经用下面的代码粘贴了 4 个文件。

    MainActivity.kt

package com.example.thesupremecounter

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import java.text.SimpleDateFormat
import java.util.*


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

        val addButton = findViewById<LinearLayout>(R.id.addButton)
        val reduceButton = findViewById<LinearLayout>(R.id.reduceButton)
        val resetButton = findViewById<LinearLayout>(R.id.resetButton)
        val myTextView = findViewById<TextView>(R.id.textView)
        val saveButton = findViewById<Button>(R.id.saveButton)
        val historyButton = findViewById<Button>(R.id.historyButton)

        var timeClicked = 0

        addButton.setOnClickListener {
            timeClicked += 1
            myTextView.text = timeClicked.toString()
//        Toast.makeText(this@MainActivity, "You clicked me.", Toast.LENGTH_SHORT).show()
        }
        reduceButton.setOnClickListener {
            timeClicked -= 1
            if (timeClicked < 0) {
                timeClicked = 0
            } else {
                myTextView.text = timeClicked.toString()
//            Toast.makeText(this@MainActivity, "You clicked me.", Toast.LENGTH_SHORT).show()
            }
        }
        resetButton.setOnClickListener {
            timeClicked = 0
            myTextView.text = timeClicked.toString()
//            Toast.makeText(this@MainActivity, "You clicked me.", Toast.LENGTH_SHORT).show()
        }

        historyButton.setOnClickListener {
            val intent = Intent(this, HistoryActivity::class.java)
            startActivity(intent)
        }
        saveButton.setOnClickListener {
            val count = timeClicked.toString()
            val c = Calendar.getInstance() // Calender Current Instance
            val dateTime = c.time // Current Date and Time of the system.
            val sdf = SimpleDateFormat("dd MMM yyyy HH:mm:ss", Locale.getDefault()) // Date Formatter
            val date = sdf.format(dateTime) // dateTime is formatted in the given format.

            val dbHandler = SqliteOpenHelper(this, null)
            dbHandler.addDate(count, date) // Add date function is called.
            Toast.makeText(this@MainActivity, count + date, Toast.LENGTH_SHORT).show()

        }
    }

}

HistoryActivity.kt

package com.example.thesupremecounter
import android.os.Bundle
import android.view.View
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager

class HistoryActivity : AppCompatActivity() {

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

        val toolbarPageTwo = findViewById<androidx.appcompat.widget.Toolbar>(R.id.toolbar_history_activity)

        setSupportActionBar(toolbarPageTwo)

        supportActionBar?.setDisplayHomeAsUpEnabled(true) //set back button
        supportActionBar?.title = "HISTORY" // Setting an title in the action bar.

        toolbarPageTwo.setNavigationOnClickListener {
            onBackPressed()
        }

        getAllCompletedDates()
    }

    private fun getAllCompletedDates() {
        val dbHandler = SqliteOpenHelper(this, null)
        val allCompletedDatesList = dbHandler.getAllCompletedDatesList()
        val tvHistory = findViewById<TextView>(R.id.tvHistory)
        val rvHistory = findViewById<androidx.recyclerview.widget.RecyclerView>(R.id.rvHistory)
        val tvNoDataAvailable = findViewById<TextView>(R.id.tvNoDataAvailable)

        if (allCompletedDatesList.size > 0) {
            tvHistory.visibility = View.VISIBLE
            rvHistory.visibility = View.VISIBLE
            tvNoDataAvailable.visibility = View.GONE

            rvHistory.layoutManager = LinearLayoutManager(this)

            val historyAdapter = HistoryAdapter(this, allCompletedDatesList)

            rvHistory.adapter = historyAdapter
        } else {
            tvHistory.visibility = View.GONE
            rvHistory.visibility = View.GONE
            tvNoDataAvailable.visibility = View.VISIBLE
        }
    }
}

SqliteOpenHelper.kt

package com.example.thesupremecounter

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

class SqliteOpenHelper(
    context: Context,
    factory: SQLiteDatabase.CursorFactory?
) :
    SQLiteOpenHelper(
        context, DATABASE_NAME,
        factory, DATABASE_VERSION
    ) {

    override fun onCreate(db: SQLiteDatabase) {
        val CREATE_HISTORY_TABLE = ("CREATE TABLE " +  TABLE_HISTORY +
               "(" + COLUMN_ID + " INTEGER PRIMARY KEY,"
               +   COLUMN_COUNT   + " TEXT,"
                + COLUMN_COMPLETED_DATE  + " TEXT" + ")")
        db.execSQL(CREATE_HISTORY_TABLE)
    }

    override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_HISTORY) // It drops the existing history table
        onCreate(db) // Calls the onCreate function so all the updated table will be created.
    }

    fun addDate(count: String, date: String ) {
        val values = "INSERT INTO history " +
                "( 'count', 'completed_date')" +
                " VALUES " +
                "( '$count', '$date')"
        val db = this.writableDatabase
        db.execSQL(values)
        db.close()
    }

    fun retrieveCount(): ArrayList<String> {
        val countList = ArrayList<String>() // ArrayList is initialized
        val db = this.readableDatabase
        val cursor = db.rawQuery("SELECT * FROM $TABLE_HISTORY", null)
        while (cursor.moveToNext())
        {countList.add(cursor.getString(cursor.getColumnIndex(COLUMN_COUNT)))
        }
        cursor.close()
        return countList

    }

    fun getAllCompletedDatesList(): ArrayList<String> {
        val list = ArrayList<String>() // ArrayList is initialized
        val db = this.readableDatabase
        val cursor = db.rawQuery("SELECT * FROM $TABLE_HISTORY", null)
        while (cursor.moveToNext())
        {list.add(cursor.getString(cursor.getColumnIndex(COLUMN_COMPLETED_DATE)))
        }
        cursor.close()
        return list
    }

    companion object {
        const val DATABASE_VERSION = 1 // This DATABASE Version
        const val DATABASE_NAME = "TheCountDatabase9.db" // Name of the DATABASE
        const val TABLE_HISTORY = "history" // Table Name
        const val COLUMN_ID = "_id" // Column Id
        const val COLUMN_COUNT = "count" // Count
        const val COLUMN_COMPLETED_DATE = "completed_date" // Column for Completed Date
    }
}

HistoryAdapter.kt

package com.example.thesupremecounter
import android.content.Context
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.item_history_row.view.*


class HistoryAdapter(val context: Context, val items: ArrayList<String>) :
    RecyclerView.Adapter<HistoryAdapter.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
            LayoutInflater.from(context).inflate(
                R.layout.item_history_row,
                parent,
                false
            )
        )
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {

        val date: String = items[position]

        holder.tvPosition.text = (position + 1).toString()
        holder.tvCount.text = "unsure what code to write here to display count values from COLUMN_COUNT + also not sure how to call the retrieve count function"
        holder.tvItem.text = date

        if (position % 2 == 0) {
            holder.llHistoryItemMain.setBackgroundColor(
                Color.parseColor("#EBEBEB")
            )
        } else {
            holder.llHistoryItemMain.setBackgroundColor(
                Color.parseColor("#FFFFFF")
            )
        }
    }

    override fun getItemCount(): Int {
        return items.size
    }

class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
    val llHistoryItemMain = view.ll_history_item_main!!
    val tvItem = view.tvItem!!
    val tvPosition = view.tvPosition!!
    val tvCount = view.tvCount!!
    }
}

任何帮助将不胜感激。

谢谢

【问题讨论】:

  • 您无法从主线程访问数据库。您可以在此处查看更多信息:stackoverflow.com/questions/44167111/…。然后,您的适配器中有一个名为 items 的列表,这是您应该用来在回收器中显示数据的列表。

标签: kotlin android-recyclerview android-sqlite


【解决方案1】:

recyclerview 旨在显示传递给它的列表的内容(在您的情况下为items)。

所以:-

holder.tvCount.text = "unsure what code to write here to display count values from COLUMN_COUNT + also not sure how to call the retrieve count function"

应该是 items 中的计数,但 items 只是日期。您需要更复杂的项目,即不仅仅是一个字符串的列表。

因此创建一个类,例如 HistoryRow,其中包含每个组件的成员,例如

data class HistoryRow(
    val id: String,
    val count: String,
    val date: String
)
  • 在下面的工作示例中,我只是将其添加为 SqliteOpenHelper 的子类

相反,在您的 getAllCompletedDatesList() 中创建一个列表,您创建一个列表并将其传递给您的适配器。

然后在 onBindViewHolder 方法/函数中,然后分配来自各个元素的值。

以下是基于上述内容的工作示例。

第一个 SqliteOpenHelper :-

class SqliteOpenHelper(
    context: Context,
    factory: SQLiteDatabase.CursorFactory?
) :
    SQLiteOpenHelper(
        context, DATABASE_NAME,
        factory, DATABASE_VERSION
    ) {

    override fun onCreate(db: SQLiteDatabase) {
        val CREATE_HISTORY_TABLE = ("CREATE TABLE " +  TABLE_HISTORY +
                "(" + COLUMN_ID + " INTEGER PRIMARY KEY,"
                +   COLUMN_COUNT   + " TEXT,"
                + COLUMN_COMPLETED_DATE  + " TEXT" + ")")
        db.execSQL(CREATE_HISTORY_TABLE)
    }

    override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_HISTORY) // It drops the existing history table
        onCreate(db) // Calls the onCreate function so all the updated table will be created.
    }

    fun addDate(count: String, date: String ) {
        val values = "INSERT INTO history " +
                "( 'count', 'completed_date')" +
                " VALUES " +
                "( '$count', '$date')"
        val db = this.writableDatabase
        db.execSQL(values)
        db.close()
    }

    fun retrieveCount(): ArrayList<String> {
        val countList = ArrayList<String>() // ArrayList is initialized
        val db = this.readableDatabase
        val cursor = db.rawQuery("SELECT * FROM $TABLE_HISTORY", null)
        while (cursor.moveToNext())
        {countList.add(cursor.getString(cursor.getColumnIndex(COLUMN_COUNT)))
        }
        cursor.close()
        return countList

    }

    fun getAllCompletedDatesList(): ArrayList<HistoryRow> {
        val list = ArrayList<HistoryRow>() // ArrayList is initialized
        val db = this.readableDatabase
        val cursor = db.rawQuery("SELECT * FROM $TABLE_HISTORY", null)
        while (cursor.moveToNext())
             list.add(
                 HistoryRow(
                 cursor.getString(cursor.getColumnIndex(COLUMN_ID)),
                     cursor.getString(cursor.getColumnIndex(COLUMN_COUNT)),
                     cursor.getString(cursor.getColumnIndex(COLUMN_COMPLETED_DATE))
             )
             )
        cursor.close()
        return list
    }

    companion object {
        const val DATABASE_VERSION = 1 // This DATABASE Version
        const val DATABASE_NAME = "TheCountDatabase9.db" // Name of the DATABASE
        const val TABLE_HISTORY = "history" // Table Name
        const val COLUMN_ID = "_id" // Column Id
        const val COLUMN_COUNT = "count" // Count
        const val COLUMN_COMPLETED_DATE = "completed_date" // Column for Completed Date
    }
    data class HistoryRow(
        val id: String,
        val count: String,
        val date: String
    )
}
  • 添加了HistoryRow 类(可能在其他地方,但为简洁起见在此处添加)
  • 注意对 getAllCompletedDatesList() 方法/函数的更改,以构建和返回 ArrayList&lt;HistoryRow&gt; 而不是 ArrayList&lt;String&gt;

所需的其他更改是 HistoryAdapter 已更改为:-

class HistoryAdapter(val context: Context, val items: ArrayList<SqliteOpenHelper.HistoryRow>) :
    RecyclerView.Adapter<HistoryAdapter.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
            LayoutInflater.from(context).inflate(
                R.layout.item_history_row,
                parent,
                false
            )
        )
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        
        holder.tvPosition.setText((position + 1).toString())
        holder.tvCount.setText(items[position].count)
        holder.tvItem.setText(items[position].date)

        if (position % 2 == 0) {
            holder.llHistoryItemMain.setBackgroundColor(
                Color.parseColor("#EBEBEB")
            )
        } else {
            holder.llHistoryItemMain.setBackgroundColor(
                Color.parseColor("#FFFFFF")
            )
        }
    }

    override fun getItemCount(): Int {
        return items.size
    }

    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val llHistoryItemMain = view.findViewById<LinearLayout>(R.id.ll_history_item_main)
        val tvItem = view.findViewById<TextView>(R.id.tvItem)
        val tvPosition = view.findViewById<TextView>(R.id.tvPosition)
        val tvCount = view.findViewById<TextView>(R.id.tvCount)
    }
}
  • items 由 ArrayList 改为 ArrayList
  • onBindViewHolder 从items 的元素中赋值
  • 我不知道为什么我必须更改 ViewHolder 才能使用 view.FindViewById 但我必须这样做。

因为我必须创建布局,所以我已经注释掉了设置工具栏,这样就不必费力地创建适当的布局了。显然布局可能会有所不同。但是,运行时获得了以下结果:-

第一次运行时:-

当点击历史时(还没有数据,正如预期的那样):-

返回 Main 并单击 SAVE 3 次,然后单击 History :-

即3 行现在与各自的数据一起显示(尽管数据相同)

【讨论】:

  • 非常感谢您。非常感激。就在检查您的回复之前,我实际上已经解决了这个问题。我将阅读您的回复并将其与我的解决方案进行比较。再次感谢:)
猜你喜欢
  • 2010-11-02
  • 1970-01-01
  • 1970-01-01
  • 2014-12-04
  • 2020-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-19
相关资源
最近更新 更多