【问题标题】:How to Run afterTextChanged off of the main thread?如何在主线程之外运行 afterTextChanged?
【发布时间】:2021-12-21 18:22:00
【问题描述】:

@Entity 生物

我正在尝试更新数据库中的 name 属性。

@Entity(primaryKeys = ["name"])
data class Creature(
    @ColumnInfo(defaultValue = "New Creature") val name: String
)

@Dao CreatureDao

更新名称的查询在这里,在 DAO 中。

@Dao
interface CreatureDao {

    [...]

    // update creature name
    @Query("UPDATE Creature SET name=:newName WHERE name=:oldName")
    fun updateCreatureName(oldName: String, newName: String)
}

我的存储库

我的视图模型通过我的存储库进行查询

class MyRepository(private val creatureDao: CreatureDao) {

    [...]

    // update creature name
    @Suppress("RedundantSuspendModifier")
    @WorkerThread
    suspend fun updateCreatureName(oldName: String, newName: String) {
        creatureDao.updateCreatureName(oldName, newName)
    }
}

SharedViewModel

这是我的视图模型调用更新名称属性的地方

class SharedViewModel(
    private val repository: MyRepository
) : ViewModel() {

    [...]

    fun updateCreatureName(oldName: String, newName: String) {
        viewModelScope.launch { repository.updateCreatureName(oldName, newName) }
    }
}

关于片段

这个视图模型的 updateCreatureName() 方法在 nameTextInputEditText 改变时从 AboutFragment 调用...

class AboutFragment() : Fragment() {

    [...]

        // update creature record when creature name is edited
        binding.nameTextInputEditText.addTextChangedListener(object : TextWatcher {
            private lateinit var oldName: String
            private lateinit var newName: String

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
                oldName = s.toString()
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                newName = s.toString()
            }

            override fun afterTextChanged(s: Editable?) {
                sharedViewModel.updateCreatureName(oldName, newName)
            }

        })
    }
}

问题

我收到错误

java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.

当我尝试启动活动片段时。我该如何运行

override fun afterTextChanged()

离开主线程?

【问题讨论】:

    标签: android-studio android-room kotlin-coroutines android-textinputedittext addtextchangedlistener


    【解决方案1】:

    您可以使用ExecutorService,然后通过Runnable 调用方法submit()。在您的类中创建一个实例或注入一个单例,以防您使用依赖注入。 也许 Jetpack 框架在这里也提供了一些更好的想法。

    【讨论】:

    • 谢谢,看起来是这样:在应用程序级别创建一个 ExecutorService 实例,配置线程池并在应用程序初始化时创建它......存储库可以接收来自查看模型并将工作移出主线程。 developer.android.com/guide/background/threading这需要我一段时间来整理和实施,但是一旦我得到它,我会发布我的过程!
    • 更新:我只需要像这样传递一个 Dispatcher:viewModelScope.launch(Dispatchers.IO) {...} 但是每次我以 任何方式更改编辑文本中的字符串时,应用程序重新启动。所以。我现在正在研究一种更好的方法。
    • 即使切换到使用 setOnEditorActionListener,当用户按下回车键时应用程序也会重新启动。 :'(
    【解决方案2】:

    关键是要使用

    viewModelScope.launch(Dispatcher.IO){...}
    

    而不是

    viewModelScope.launch{...}
    

    "当你没有传递一个 Dispatcher 来启动时,任何协程启动 从 viewModelScope 在主线程中运行。” source

    【讨论】:

      猜你喜欢
      • 2018-03-04
      • 2010-12-04
      • 1970-01-01
      • 2021-12-07
      • 1970-01-01
      • 2011-04-29
      • 2013-09-02
      • 2016-05-02
      • 2015-03-25
      相关资源
      最近更新 更多