#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
, и переназначает переменную для хранения совершенно нового списка. Ваш адаптер ничего не знает об этом новом списке — у него все еще есть ссылка на старый список.
Поэтому у вас есть несколько вариантов:
- Пусть у вас
ArticleListAdapter
естьsetData
метод, который принимает новый список. ЭтоsetData
обновило бы списокArcticleListAdapter
, который отслеживается (и, в качестве преимущества, он также может вызывать внутреннеnotifyDataSetChanged()
, что делает его всегда вызываемым. - Обновите список
viewModel.articleList
новыми записями, а не заменяйте весь список, тем самым гарантируя, что вArticleListAdapter
используемом списке будут ваши обновленные данные:
viewModel.articleLiveData.observe(viewLifecycleOwner, { result ->
val HomePages = result.getOrNull()
viewModel.articleList.clear()
if (HomePages != null) {
viewModel.articleList.addAll(HomePages)
}
adapter.notifyDataSetChanged()
})
- Сделайте свой
ArticleListAdapter
ListAdapter
выбор . Этот класс обрабатывает отслеживание списка данных для вас и предоставляет вам простойsubmitList
метод, который вы бы вызвали из своегоobserve
метода. В качестве побочного преимущества он используетDiffUtil
то, что намного эффективнееnotifyDataSetChanged()
.
Комментарии:
1. Проблема остается нерешенной. И в моем
Repository.getHomeArticles(page)
у меня есть эта строка кодаLog.d(TAG, "getHomeArticles: Start requesting data")
. Я проверил Logcat и не могу найти эту строку журнала. Это показывает, чтоRepository.getHomeArticles(page)
не выполняется. Поэтому данные не запрашиваются с сервера.