Пользовательский интерфейс не будет обновляться после изменения данных LiveData

#android #android-livedata #android-jetpack

Вопрос:

Вот мой код:

 class HomeFragment : Fragment() {
    val viewModel by lazy {
        ViewModelProvider(this)[HomeViewModel::class.java]
    }

    private lateinit var adapter: ArticleListAdapter

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val root = inflater.inflate(R.layout.fragment_home, container, false)
        return root
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        val linearLayoutManager = LinearLayoutManager(activity)
        rv_home.layoutManager = linearLayoutManager
        adapter = ArticleListAdapter(viewModel.articleList)
        rv_home.adapter = adapter
        viewModel.getHomeArticle(0)


        viewModel.articleLiveData.observe(viewLifecycleOwner, { result ->
            val HomePages = result.getOrNull()
            viewModel.articleList = HomePages
            adapter.notifyDataSetChanged()
        })
    }

}
 
 class HomeViewModel : ViewModel() {
    var articleList: HomeArticleBean? = null
    private val observerArticleLiveData = MutableLiveData<Int>()
    val articleLiveData = Transformations.switchMap(observerArticleLiveData) { page ->
        Repository.getHomeArticles(page)
    }

    fun getHomeArticle(page: Int) {
        observerArticleLiveData.value = page
    }
}
 

Когда я вызываю getHomeArticle() из HomeFragment,программа должна выполняться

 Repository.getHomeArticles(page)
 

Но после Дубуга я обнаружил, что эта строка кода не будет выполнена.
Это привело к тому, что мое наблюдение articleLiveData в домашнем фрагменте оказалось недействительным, что не позволило мне обновить пользовательский интерфейс. Я новичок в Jetpack, поэтому не знаю, почему это происходит, мой код был написан после чужого кода, и у меня не было проблем с запуском его кода, я внимательно посмотрел, есть ли различия между моим кодом и его, но ничего не нашел. Я долго ищу в сети. Но бесполезно. Пожалуйста, помогите или попробуйте дать некоторые идеи о том, как этого достичь. Заранее спасибо.

Ответ №1:

Ваша проблема в том, что вы используете viewModel.articleList :

    adapter = ArticleListAdapter(viewModel.articleList)
 

Это создает ваш адаптер и привязывает его данные к списку, хранящемуся в данный момент viewModel.articleList (которого по какой-то причине нет в вашем HomeViewModel коде?)

    viewModel.articleList = HomePages
 

Эта строка полностью отбрасывает список, хранящийся в данный момент viewModel.articleList , и переназначает переменную для хранения совершенно нового списка. Ваш адаптер ничего не знает об этом новом списке — у него все еще есть ссылка на старый список.

Поэтому у вас есть несколько вариантов:

  1. Пусть у вас ArticleListAdapter есть setData метод, который принимает новый список. Это setData обновило бы список ArcticleListAdapter , который отслеживается (и, в качестве преимущества, он также может вызывать внутренне notifyDataSetChanged() , что делает его всегда вызываемым.
  2. Обновите список viewModel.articleList новыми записями, а не заменяйте весь список, тем самым гарантируя, что в ArticleListAdapter используемом списке будут ваши обновленные данные:
 viewModel.articleLiveData.observe(viewLifecycleOwner, { result ->
    val HomePages = result.getOrNull()
    viewModel.articleList.clear()
    if (HomePages != null) {
        viewModel.articleList.addAll(HomePages)
    }
    adapter.notifyDataSetChanged()
})
 
  1. Сделайте свой ArticleListAdapter ListAdapter выбор . Этот класс обрабатывает отслеживание списка данных для вас и предоставляет вам простой submitList метод, который вы бы вызвали из своего observe метода. В качестве побочного преимущества он использует DiffUtil то, что намного эффективнее notifyDataSetChanged() .

Комментарии:

1. Проблема остается нерешенной. И в моем Repository.getHomeArticles(page) у меня есть эта строка кода Log.d(TAG, "getHomeArticles: Start requesting data") . Я проверил Logcat и не могу найти эту строку журнала. Это показывает, что Repository.getHomeArticles(page) не выполняется. Поэтому данные не запрашиваются с сервера.