如何使用视图模型和实时数据将参数传递给我的 Word Dao 进行查询?

how to pass a parameter to my Word Dao for query using View Model and Live Data?

更新:如何使用ViewModelFactory,是否有必要使用它来传递我们的参数?有什么好处?这会打破实时数据概念吗?

我想向我的房间数据库的word Dao发送一个参数进行查询,但在我的情况下,我不知道如何传递该参数。所以让我们从代码开始...... WordDao.kt

@Dao
interface WordDao {

    @Insert
    fun insert(word: Word)

    @Update
    fun update(word: Word)

    @Delete
    fun delete(word: Word)

    @Query("delete from En_Fa")
    fun deleteAllNotes()

    @Query("SELECT * FROM En_Fa ORDER BY id ASC")
    fun getAllNotes(): LiveData<List<Word>>

    @Query("Select * From En_Fa WHERE date == :today ")
    fun getTodayWords(today: String): LiveData<List<Word>>
}

WordRepository.kt

class WordRepository(private val wordDao: WordDao, today: String) {

    val readAllData: LiveData<List<Word>> = wordDao.getAllNotes()
    val readToday: LiveData<List<Word>> = wordDao.getTodayWords(today)


    fun addWord(word: Word) {
        wordDao.insert(word)
    }
}

WordViewModel.kt

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

    val readAllData2: LiveData<List<Word>>

    private val repository: WordRepository

    init {

        val wordDao = WordDatabase.getInstance(application).wordDao()

        repository = WordRepository(wordDao, today)
        readAllData2 = repository.readToday

    }

    fun addWord(word: Word){
        viewModelScope.launch(Dispatchers.IO){
            repository.addWord(word)
        }
    }

}

这是我的代码行,它在我的片段

中创建了这个 wordview 模型的对象 class
private val mWordViewModel: WordViewModel by viewModels()

那么如何将我的(今天)变量从我的片段传递到我的 WordViewModel class

如果我答对了你的问题, 首先,您需要创建一个函数来 return 要观察的 liveData 对象,然后您需要使用 ViewModelProviders 来为您提供片段中的 ViewModel 对象。

mWordViewModel: WordViewModel = ViewModelProvider(this/getActivity()).get(WordViewModel::class.java)
mWordViewModel.getLiveDataFunction().observe(this/lifeCycleOwner, {
    process result/response here
}

那就直接用吧。

mWordViewModel.addWord(today)

我想你正在寻找这个:


@Dao
interface WordDao {
// ...
    @Query("Select * From En_Fa WHERE date == :today ")
    fun getTodayWords2(today: String): <List<Word>
}

然后在存储库中:

class WordRepository{
  // ... ...
  var mutableWords: MutableLiveData<List<Word>> = MutableLiveData()

  fun getWords(today: String): List<Word> {  // WARNING! run this in background thread else it will crash
    return wordDao.getTodayWords2(today)
  }

  fun getWordsAsync(today: String) {
   Executors.newSingleThreadExecutor().execute { 
          val words = getWords(today)
          liveWords.postValue(words)   // <-- just doing this will trigger the observer and do next thing, such as, updating ui
        }
  }
}

然后在你的 viewModel 中:

class WordViewModel(application: Application): AndroidViewModel(application) {
  // ... ...

  val liveWords: LiveData<List<Word>> = repository.mutableWords

  fun getWordsAsync(today: String) {
    repository.getWordsAsync(today)
  }
}

然后终于在你的 activity / 片段中:

fun viewModelDemo() {
  mWordViewModel.liveWords.observe(this, Observer{
    // todo: update the ui, eg
    someTextView.text = it.toString()    // <-- here you get the output
   })


   someButton.setOnClickListener{
// here you give the input
  mWordViewModel.getWordsAsync(today)  // get `today` from date picker or something    
   }
}

编辑

所以你有一个带有适配器的 recyclerView。当数据集发生变化时,您调用 notifyDataSetChanged。假设,适配器看起来像这样:

class MyAdapter: RecyclerView.Adapter<ViewHolder> {
  private var words: List<Word> = ArrayList() // initially points to an empty list

  override fun getCount() { return words.size }
  // ... ... other methods

  // public method:
  fun submitList(words1: List<Word>) {
    this.words = words1  // so now it points to the submitted list
    this.notifyDataSetChanged()  // this tells recyclerView to update itself
  }  

}

然后在您的 activity 或片段中:

private lateinit var myAdapter: MyAdapter

override fun onCreate() {  // or onViewCreated if using fragment
  // ... ... some codes
  this.myAdapter = MyAdapter()
  binding.recyclerView.adapter = myAdapter

  viewModelDemo()
}

fun viewModelDemo() {
  mWordViewModel.liveWords.observe(this, Observer{
    // todo: update the ui, eg
    myAdapter.submitList(it)    // <----- Here you call the submitList method

    // <-- here you get the output
   })
  // --- ---
}

我希望这能奏效。