Breaking News Fragment
Learn how to load data to our fragments from the ViewModel
We'll cover the following...
Understanding the breaking news fragment
In this fragment, a list of articles is loaded into a RecyclerView
. The adapter has an onClick
listener set on the articles so that when an item is clicked, a WebView
is opened within the application where the user can read the article.
The fragment has been optimized with various features to improve the application’s data handling, performance, and efficiency. These features include using ViewBinding
and coroutines. These technologies help to improve the structure and organization of the code, as well as the efficiency and speed of the application. Let’s break it down for better comprehension.
package com.example.ui.fragmentsimport android.os.Bundleimport android.util.Logimport androidx.fragment.app.Fragmentimport android.view.LayoutInflaterimport android.view.Viewimport android.view.ViewGroupimport android.widget.AbsListViewimport android.widget.Adapterimport android.widget.Toastimport androidx.activity.viewModelsimport androidx.lifecycle.Observerimport androidx.lifecycle.ViewModelProviderimport androidx.navigation.fragment.findNavControllerimport androidx.recyclerview.widget.LinearLayoutManagerimport androidx.recyclerview.widget.RecyclerViewimport com.example.newsapplication.Rimport com.example.newsapplication.databinding.FragmentBreakingNewsBindingimport com.example.newsapplication.db.ArticleDatabaseimport com.example.newsapplication.repository.NewsRepositoryimport com.example.newsapplication.util.Constants.Companion.QUERY_PAGE_SIZEimport com.example.newsapplication.util.Resourceimport com.example.newsapplication.viewModel.NewsViewModelimport com.example.newsapplication.viewModel.NewsViewModelProviderimport com.example.ui.activities.NewsActivityimport com.example.ui.adapters.NewsAdapterclass BreakingNewsFragment : Fragment(R.layout.fragment_breaking_news) {lateinit var viewModel: NewsViewModellateinit var newsAdapter: NewsAdapterprivate lateinit var binding: FragmentBreakingNewsBindingoverride fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)binding = FragmentBreakingNewsBinding.bind(view)setUpRecyclerView(binding)val newsRepository = NewsRepository(ArticleDatabase(requireContext() as NewsActivity))val viewModelProviderFactory =NewsViewModelProvider(activity?.application!!, newsRepository)viewModel = ViewModelProvider(this, viewModelProviderFactory).get(NewsViewModel::class.java)newsAdapter.setOnItemClickListener {val bundle = Bundle().apply {putSerializable("article", it)}findNavController().navigate(R.id.action_breakingNewsFragment2_to_articleFragment,bundle)}viewLifecycleOwner.lifecycleScope.launchWhenStarted {viewModel.getBreakingNews.collect {newsAdapter.differ.submitList(it?.data)it ?: return@collectshowProgressBar(binding)when (it.status) {Resource.Status.SUCCESS -> {hideProgressBar(binding)hideErrorMessage()Toast.makeText(activity, "Success", Toast.LENGTH_LONG).show()}Resource.Status.LOADING -> {Toast.makeText(activity,"Wait for data. Data is loading...",Toast.LENGTH_LONG).show()}Resource.Status.ERROR -> {showErrorMessage("Sorry!!!,Something went wrong")}Resource.Status.FAILURE -> {showErrorMessage("Sorry!!!,Something went terribly wrong")}}}}}override fun onStart() {super.onStart()viewModel.onStart()Toast.makeText(activity, "start", Toast.LENGTH_LONG).show()}private fun hideProgressBar(binding: FragmentBreakingNewsBinding) {binding.paginationProgressBar.visibility = View.INVISIBLE}private fun showProgressBar(binding: FragmentBreakingNewsBinding) {binding.paginationProgressBar.visibility = View.VISIBLE}private fun hideErrorMessage() {binding.itemErrorMessage.visibility = View.INVISIBLE}private fun showErrorMessage(message: String) {binding.itemErrorMessage.visibility = View.VISIBLEbinding.errorMessage.text = message}private fun setUpRecyclerView(binding: FragmentBreakingNewsBinding) {newsAdapter = NewsAdapter()binding.breakingNewsRecyclerView.apply {adapter = newsAdapterlayoutManager = LinearLayoutManager(activity)}}}
In the below code snippet, we declare class variables as references to the NewsAdapter
and the ViewBinding
classes.
All three variables are marked with the lateinit
keyword. This means that the variables will be initialized later in the code, but they don’t have to be initialized when they’re declared.
lateinit var viewModel: NewsViewModel
lateinit var newsAdapter: NewsAdapter
private lateinit var binding: FragmentBreakingNewsBinding
private val TAG = "BreakingNewsFragment"
We use ViewBinding
to bind the views with the Android data ...