1

活动接收意图

class AddNoteActivity : AppCompatActivity() {

     private lateinit var addViewModel: NoteViewModel
     private lateinit var titleEditText: TextInputEditText
     private lateinit var contentEditText: TextInputEditText

 override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_add_note_activty)
        setSupportActionBar(toolbar)

        addViewModel = ViewModelProviders.of(this).get(NoteViewModel::class.java)
        titleEditText = findViewById(R.id.itemTitle)
        contentEditText = findViewById(R.id.itemNote)


           val extra = intent.extras
            if (extra != null) {
                val uuid = extra.getLong("UUID")
                val note: Notes? = addViewModel.getNote(uuid)
                titleEditText.setText(note!!.title)
                contentEditText.setText(note.note)
             }
      }
}

NoteViewModel 类

class NoteViewModel(application: Application) : AndroidViewModel(application) {
    companion object {
             private var note: Notes = Notes(0, "", "test title", "test ontent")
            }


    fun getNote(uuid: Long?): Notes {
            val job = async(CommonPool) {
                getNoteAsyncTask(notesDatabase).execute(uuid)
            }
            runBlocking { job.await() }
            return note
    }

    class getNoteAsyncTask(database: NotesDatabase) : AsyncTask<Long, Unit, Unit>() {

        private val db: NotesDatabase = database

        override fun doInBackground(vararg params: Long?) {
            note = db.notesDataDao().getNote(params[0])
        }
    }

}

如果我通过一个意图从数据库中获取一个带有 uuid 的 Note 对象,并在 titleEditText 和 contentEditText 中设置接收到的数据,那么 Note 中的数据集来自我们单击 RecyclerView 中的 Note 项时调用的先前意图。在第一次单击 Note 项目时,我得到了我设置的“测试标题”和“测试内容”的默认值。

上述是大多数时候的行为。有时,titleEditText 和 contentEditText 中的数据集属于正确的 Note 对象。

有人可以告诉我我做错了什么吗?如何纠正我的应用行为?

4

1 回答 1

1

不幸的是,在使用视图模型向视图(AddNoteActivity)提供数据的方式上存在很大的错误。

基本上,您的视图永远没有机会等待获取数据,因为它总是接收默认值。发生这种情况是因为AsyncTask协程在其自己的线程池上运行,因此协程立即完成并返回默认值。

您应该考虑使用LiveData将新对象发布到您的视图并重构您的视图模型。

因此,您需要对数据库进行同步查询并观察对笔记的更改,而不是使用 getter。当然,在现实生活场景中,拥有不同类型的状态以便能够在用户等待时显示微调器可能是一个好主意。但这是另一个大问题。因此,为了简单起见,请考虑将您的视图模型更改为以下内容:

class NoteViewModel(private val database: NotesDatabase) : ViewModel { // you do not need an application class here
    private val _notes = MutableLiveData<Notes>()
    val notes: LiveData<Notes> = _notes

    fun loadNotes(uuid: Long) {
        launch(CommonPool) {
            val notes = database.notesDataDao().getNote(uuid)
            _notes.setValue(notes)
        }
    }
}

然后,您可以观察活动中注释字段的变化。

class AddNoteActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // ...

        val noteViewModel = ViewModelProviders.of(this).get(NoteViewModel::class.java)
        noteViewModel.notes.observe(this, Observer {
            title.text = it.title
            content.text = it.note
        })
    }
}

您还需要使用ViewModelProvider.Factory来创建您的视图模型并将依赖项正确注入其中。尽量避免在那里有上下文,因为它使测试变得更加困难。

于 2018-06-16T08:00:49.323 回答