Почему по-прежнему нужно запускать notifyDataSetChanged (), когда я использовал LiveData? - PullRequest
0 голосов
/ 11 марта 2020

Я учусь Room с примером проекта RoomWordsSample на https://github.com/googlecodelabs/android-room-with-a-view/tree/kotlin.

Следующий код взят из проекта.

На мой взгляд, LiveDate будет обновлять пользовательский интерфейс автоматически при изменении данных, если они наблюдались.

Но в файле WordListAdapter.kt я обнаружил, что notifyDataSetChanged() добавлено к function setWords(words: List<Word>) , Кажется, что он должен уведомлять пользовательский интерфейс вручную при изменении данных.

Почему все еще требуется запуск notifyDataSetChanged(), когда я использовал LiveData?

MainActivity.kt

class MainActivity : AppCompatActivity() {

    private val newWordActivityRequestCode = 1
    private lateinit var wordViewModel: WordViewModel

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

        val recyclerView = findViewById<RecyclerView>(R.id.recyclerview)
        val adapter = WordListAdapter(this)
        recyclerView.adapter = adapter
        recyclerView.layoutManager = LinearLayoutManager(this)

        wordViewModel = ViewModelProvider(this).get(WordViewModel::class.java)


        wordViewModel.allWords.observe(this, Observer { words ->         
            words?.let { adapter.setWords(it) }
        })

    }
}

WordViewModel.kt

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

    private val repository: WordRepository 
    val allWords: LiveData<List<Word>>

    init {

        val wordsDao = WordRoomDatabase.getDatabase(application, viewModelScope).wordDao()
        repository = WordRepository(wordsDao)
        allWords = repository.allWords
    }


    fun insert(word: Word) = viewModelScope.launch {
        repository.insert(word)
    }
}

WordListAdapter.kt

class WordListAdapter internal constructor(
        context: Context
) : RecyclerView.Adapter<WordListAdapter.WordViewHolder>() {

    private val inflater: LayoutInflater = LayoutInflater.from(context)
    private var words = emptyList<Word>() // Cached copy of words

    inner class WordViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val wordItemView: TextView = itemView.findViewById(R.id.textView)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WordViewHolder {
        val itemView = inflater.inflate(R.layout.recyclerview_item, parent, false)
        return WordViewHolder(itemView)
    }

    override fun onBindViewHolder(holder: WordViewHolder, position: Int) {
        val current = words[position]
        holder.wordItemView.text = current.word
    }

    internal fun setWords(words: List<Word>) {
        this.words = words
        notifyDataSetChanged()
    }

    override fun getItemCount() = words.size
}

Ответы [ 2 ]

3 голосов
/ 11 марта 2020

На самом деле, livedata даст вам обновленные данные в вашей деятельности. Но теперь ваша работа заключается в обновлении интерфейса. Таким образом, всякий раз, когда текущие данные дают вам обновленные данные, вы должны будете сказать пользовательскому интерфейсу обновить данные. Следовательно, notifyDataSetChanged().

1 голос
/ 11 марта 2020

notifyDataSetChanged не имеет ничего общего с LiveData, это часть RecyclerView API.

LiveData - это способ получения данных с учетом жизненного цикла, RecyclerView просто отображает представления.

...