【问题标题】:StartActivityForResult called twice using Room, Coroutine and ViewModelStartActivityForResult 使用 Room、Coroutine 和 ViewModel 调用了两次
【发布时间】:2019-08-17 22:29:35
【问题描述】:

当我从另一个人回来参加活动时,我遇到了问题。 在我的活动中,我使用 ViewModel,当活动创建时,我调用 challengeDayViewModel.daysForChallenge 并观察变化。数据准备好后,我将它们设置在适配器上。在适配器中,当我单击项目时,我调用challengeDayViewModel.getChallengeDay(dayId) 并观察结果。当它准备好时,我开始活动以传递检索到的对象的属性。在 CountdownActivity 我做了一些事情,当我回来时,在onActivityResult 方法中,我使用 challengeDayViewModel.setDayDone(selectedDayId) 更新数据库中的数据,问题就在这里。评论我在数据库中更新数据的行一切正常,但如果我添加更新行,更新完成,但在他重新运行 rown startActivityForResult(intent, ActivityRequestCode.COUNTDOWN_CODE) 后再次打开 CountdownActivity(我在调试中看到)

class ChallengeDayActivity: AppCompatActivity() {

    private var selectedDayId: Long = 0
    private lateinit var adapter: ChallengeDayAdapter

    private val challengeDayViewModel: ChallengeDayViewModel by lazy {
        ViewModelProvider.AndroidViewModelFactory.getInstance(application).create(ChallengeDayViewModel::class.java)
    }

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

        val recyclerView = challenge_day_recyclerview
        adapter = ChallengeDayAdapter(this)

        recyclerView.adapter = adapter
        recyclerView.layoutManager = GridLayoutManager(this, 3)

        challengeDayViewModel.daysForChallenge.observe(this, Observer { challengeDayList ->
            challengeDayList.let {
                adapter.setChallengeDay(challengeDayList)
                adapter.notifyDataSetChanged()
            }
        })

        adapter.goToCountdown = { dayId ->
            selectedDayId = dayId
            challengeDayViewModel.getChallengeDay(dayId).observe(this, Observer { challengeDay ->
                val intent = Intent(this, CountdownActivity::class.java).apply {
                    putExtra("seconds", challengeDay.seconds)
                }

                startActivityForResult(intent, ActivityRequestCode.COUNTDOWN_CODE)
            })
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == ActivityRequestCode.COUNTDOWN_CODE && resultCode == Activity.RESULT_OK) {
            challengeDayViewModel.setDayDone(selectedDayId)
            Snackbar.make(coordinator, "BUBU", Snackbar.LENGTH_LONG).show()
        }

    }
}

我的视图模型是

class ChallengeDayViewModel: ViewModel() {

    private val challengeDayRepository: ChallengeDayRepository

    val daysForChallenge: LiveData<List<ChallengeDay>>

    init {
        val challengeDayDao = database.challengeDayDao()

        challengeDayRepository = ChallengeDayRepository(challengeDayDao)

        daysForChallenge = challengeDayRepository.getChallengeDayForStandardChallenge()
    }

    fun setDayDone(challengeDayId: Long) = viewModelScope.launch(Dispatchers.IO) {
        challengeDayRepository.setDayDone(challengeDayId)
    }

    fun getChallengeDay(challengeDayId: Long): LiveData<ChallengeDay> = challengeDayRepository.getChallengeDay(challengeDayId)
}

我的 DAO

@Dao
interface ChallengeDayDao {

    @Query("SELECT * FROM CHALLENGE_DAY WHERE CHD_ID_PK = :challengeDayId")
    fun getChallengeDay(challengeDayId: Long): LiveData<ChallengeDay>

    @Query("SELECT * FROM CHALLENGE_DAY WHERE CHG_ID_FK = :challengeId")
    fun getChallengeDayForChallenge(challengeId: Long): LiveData<List<ChallengeDay>>

    @Query("SELECT CHD.* FROM CHALLENGE_DAY CHD JOIN CHALLENGE CHG ON CHD.CHG_ID_FK = CHG.CHG_ID_PK WHERE CHG.CHG_STANDARD = 1")
    fun getStandardChallengeDayForChallenge(): LiveData<List<ChallengeDay>>

    @Query("UPDATE CHALLENGE_DAY SET CHD_DONE = 1 WHERE CHD_ID_PK = :challengeDayId")
    suspend fun setDayDone(challengeDayId: Long)

    @Insert
    suspend fun insert(challengeDay: ChallengeDay)

    @Insert
    suspend fun insertAll(challengeDay: List<ChallengeDay>): List<Long>
}

在回来的 CountdownActivity 中我有这个代码

alert("Test message", "Test title") {
    okButton {
        setResult(Activity.RESULT_OK)
        finish()
    }
}.show()

这里是存储库的代码

class ChallengeDayRepository(private val challengeDayDao: ChallengeDayDao) {

    @WorkerThread
    fun getChallengeDay(challengeDayId: Long): LiveData<ChallengeDay> = challengeDayDao.getChallengeDay(challengeDayId)

    @WorkerThread
    fun getAllChallengeDaysForChallenge(challengeId: Long): LiveData<List<ChallengeDay>> = challengeDayDao.getChallengeDayForChallenge(challengeId)

    @WorkerThread
    fun getChallengeDayForStandardChallenge(): LiveData<List<ChallengeDay>> = challengeDayDao.getStandardChallengeDayForChallenge()

    @WorkerThread
    suspend fun setDayDone(challengeDayId: Long) = challengeDayDao.setDayDone(challengeDayId)

    @WorkerThread
    suspend fun insert(challengeDay: ChallengeDay) = challengeDayDao.insert(challengeDay)

    @WorkerThread
    suspend fun insertAll(challengeDay: List<ChallengeDay>): List<Long> = challengeDayDao.insertAll(challengeDay)

}

【问题讨论】:

  • 可能你在'ChallengeDayRepository'中更新了两次'getChallengeDay' liveData,也请分享'ChallengeDayRepository'的代码,以便我们理解和帮助你。
  • 我添加了 ChallengeDayRepository 的代码

标签: android kotlin android-room android-viewmodel


【解决方案1】:

同样的问题已经被问到:this thread

检查该帖子中的答案。 防止观察重复的解决方案之一也是使用 SingleEvent LiveData:- 可以找到源文章 here,这意味着您只使用一次数据。

open class Event<out T>(private val content: T) {

    var hasBeenHandled = false
        private set

    /**
     * Returns the content and prevents its use again.
     */
    fun getContentIfNotHandled(): T? {
        return if (hasBeenHandled) {
            null
        } else {
            hasBeenHandled = true
            content
        }
    }

    /**
     * Returns the content, even if it's already been handled.
     */
    fun peekContent(): T = content
}

【讨论】:

    【解决方案2】:

    this thread 启发,我写这篇文章来解决我的问题。

    fun <T> LiveData<T>.observeOnce(lifecycleOwner: LifecycleOwner, observer: Observer<T>) {
        observe(lifecycleOwner, object: Observer<T> {
            override fun onChanged(t: T?) {
                observer.onChanged(t)
                removeObserver(this)
            }
        })
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-03
      • 1970-01-01
      • 2017-06-25
      • 2013-01-21
      相关资源
      最近更新 更多