没有 livedata 的 Android Studio Room 数据

如何解决没有 livedata 的 Android Studio Room 数据

我得到了以下 Room 数据库,想在 textview 中输出随机用户名称。不幸的是,运行代码会产生输出kotlin.unit 在 textview 中。我的文件看起来像这样:

MainActivity.kt

class MainActivity : AppCompatActivity() {

    private lateinit var mNameviewmodel: Nameviewmodel

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

        mNameviewmodel = viewmodelProvider(this).get(Nameviewmodel::class.java)

        val btn = findViewById<Button>(R.id.btn_addName)
        val tv = findViewById<TextView>(R.id.tv_showName)

        btn.setonClickListener {
            val text = findViewById<EditText>(R.id.et_enterName)?.text.toString()
            val name = Name(0,text)

            // Add Data to Database
            mNameviewmodel.addName(name)
            Toast.makeText(applicationContext,"Successfully added $text.",Toast.LENGTH_LONG).show()

            val randomName = mNameviewmodel.getRandomName()

            // Without .toString() I get an error,with it it displays kotlin.unit
            tv.text = randomName.toString() 
        }

    }
}

activity_main.xml

<?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">

    <TextView
        android:id="@+id/tv_showName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.133" />

    <EditText
        android:id="@+id/et_enterName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="textPersonName"
        android:hint="Name"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.497"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.244" />

    <Button
        android:id="@+id/btn_addName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.379" />

</androidx.constraintlayout.widget.ConstraintLayout>

名称.kt

@Entity(tableName = "name_data")
data class Name (
    @PrimaryKey(autoGenerate = true) val id: Int,@ColumnInfo(name = "name") val name: String
)

NameDao.kt

@Dao
interface NameDao {

    @Insert
    fun addName(name: Name)

    @Query("SELECT name FROM name_data ORDER BY RANDOM() LIMIT 1")
    fun getRandomName(): String
}

NameDatabase.kt

@Database(entities = [Name::class],version = 1,exportSchema = false)
abstract class NameDatabase: RoomDatabase() {

    abstract fun nameDao(): NameDao

    companion object{
        @Volatile
        private var INSTANCE: NameDatabase? = null

        fun getDatabase(context: Context): NameDatabase{
            val tempInstance = INSTANCE
            if(tempInstance != null){
                return tempInstance
            }
            synchronized(this){
                val instance = databaseBuilder(
                    context.applicationContext,NameDatabase::class.java,"name_data"
                ).build()
                INSTANCE = instance
                return instance
            }
        }
    }
}

NameRepository.kt

class NameRepository(private val nameDao: NameDao) {

     fun getRandomName() { nameDao.getRandomName() }

     fun addName(name: Name) { nameDao.addName(name) }
}

Nameviewmodel.kt

class Nameviewmodel(application: Application): Androidviewmodel(application) {

    private val repository: NameRepository

    init {
        val nameDao = NameDatabase.getDatabase(application).nameDao()
        repository = NameRepository(nameDao)
    }

    fun addName(name: Name) {
        viewmodelScope.launch(dispatchers.IO){
            repository.addName(name)
        }
    }

    fun getRandomName() {
        viewmodelScope.launch(dispatchers.IO){
            repository.getRandomName()
        }
    }
}

这是按下按钮时textview的输出方式。

How it looks when pressing the button

尽管数据库已填充。

Database gets populated

感谢任何帮助显示数据。谢谢!

解决方法

问题在于,在 viewmodel 中的 getRandomNumber 方法中,您没有返回任何内容,这就是您得到 kotlin.unit 的原因。你应该确保返回一个值

可能的解决方案如下。

  1. 在您的 dao 中创建一个方法,该方法接受一个数字并返回该行(这基本上是随机名称)
  2. 从您的 repo 中使用随机数调用该方法,您可以使用 Random.getNextInt 不确定如何获得随机数
  3. 从您的视图模型调用该方法
  4. 从你的按钮 onClick 调用 viewModel 方法

确保在适用的情况下使用 suspend 以获得结果。对于我上面展示的情况,将在视图级别启动协程并进行其余调用 (vm,repo,dao) suspend

,

所以经过一些测试和来回这就是我所拥有的,它似乎正在工作。 如果有人要带一些东西,我很乐意接受它们,并非常感谢 georkost 提供所有有用的提示!

// No changes made to database

@Entity(tableName = "name_data")
data class Name (
    @PrimaryKey(autoGenerate = true) val id: Int,@ColumnInfo(name = "name") val name: String
)

//*********************************************************************************

// Changed return type from Query to LiveData<String> (was just String before)

@Dao
interface NameDao {

    @Insert
    fun addName(name: Name)

    @Query("SELECT name FROM name_data ORDER BY RANDOM() LIMIT 1")
    fun getRandomName(): LiveData<String>    // HERE
}

//*********************************************************************************

// Changed getRandomMeal from fun to val

class NameRepository(private val nameDao: NameDao) {

     val getRandomMeal: LiveData<String> = nameDao.getRandomName()  // HERE

     fun addName(name: Name) { nameDao.addName(name) }
}

//*********************************************************************************

// Added getRandomName val,initialized it and removed the fun

class NameViewModel(application: Application): AndroidViewModel(application) {

    val getRandomName: LiveData<String>             // HERE
    private val repository: NameRepository

    init {
        val nameDao = NameDatabase.getDatabase(application).nameDao()
        repository = NameRepository(nameDao)
        getRandomName = repository.getRandomMeal    // HERE
    }

    fun addName(name: Name) {
        viewModelScope.launch(Dispatchers.IO){
            repository.addName(name)
        }
    }
}

//*********************************************************************************

// Changed the last row to observe the LiveData and display it in the Text View

class MainActivity : AppCompatActivity() {

    private lateinit var mNameViewModel: NameViewModel

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

        mNameViewModel = ViewModelProvider(this).get(NameViewModel::class.java)

        val btn = findViewById<Button>(R.id.btn_addName)
        val tv = findViewById<TextView>(R.id.tv_showName)

        btn.setOnClickListener {
            val text = findViewById<EditText>(R.id.et_enterName)?.text.toString()
            val name = Name(0,text)

            // Add Data to Database
            mNameViewModel.addName(name)
            Toast.makeText(applicationContext,"Successfully added $text.",Toast.LENGTH_LONG).show()

            // HERE
            mNameViewModel.getRandomName.observe(this,Observer { String -> tv.text = String })


        }
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?