NewsFly ✈️ An app featuring MVVM, Navigation Component, Flow, Pagination, Search, Room, Data Store, Hilt (Clean Architecture)

Inuwa Ibrahim
6 min readOct 9, 2021

I’ll be showing you how to build an all in one ‘News application’ which features virtually every thing you would ever need in building a modern performant android application.

I call this application — NewsFly ✈️

Features

….Light and Dark Mode, Offline Capability, Search, Retrofit, Glide, Shimmer View and lots more 🌝

Final App

Here is what our final app will look like:

Full Code

If you are the type that just wanna jump straight to the codebase, I got you covered:
Link to full code on github

What to do before moving on with this article?

You have to check the full code on GitHub for dependencies used, xml used (Layouts, Custom views) and other classes.

In order to reduce complexities, this article focuses on:

Retrieving, Storing and Displaying of data (news)

Architecture

The architecture used for this application is:

MVVM — Model - View - View Model.

I would explain this using the diagram below: (Pay attention 👀)

fig 1

Let’s start from the ground up (Bottom), all the way to the top from fig 1.

Using the diagram above, we would take each of the layer and see how they all connect to build a well structured application. (NewsFly ✈️)

WebService:

In simple terms, this layer consist of HOW and WHERE you are getting your data from (In this case, a list of news post)

How and Where?
How: Retrofit
Where: NewsApi

I would assume you have Retrofit setup using hilt. If not, check how I did same in this article

  • Create a Package: Name that → “network
  • Inside “network” package, create a new Interface, Name that → “ApiService

So, now that we know where we want to get our news articles from, what’s next?

More Layered Structure

This is not necessary, but I love to have a “middle man” that interacts with ApiService

  • Create a new package, name that → data
  • Under data, create a new Kotlin File/Class, call that → “ApiDataSource
  • As you can see, I made a reference to “ApiService” using hilt, which we created earlier under “network” package
  • Using Coroutines, we perform the magic of making the network request “asynchronously”

SQLITE

The next thing shown in our reference image (fig 1) (bottom left) is SqLite.

SqLite is basically a relational database management system.

We want our users to be able to view some contents when the app is offline (without internet) or with a slow internet connection.

How to achieve this:
Room Database
If you are new to room database, check this article I wrote:
Article on room to get an overview of storage on android

  • Create a new Package, call that “database
  • Under “database”, create 3 new packages call them → dao, entity, and main
  • Under entity, create 2 new classes → RecentArticle and AllNewsRemotekey[These are our Model (See fig.1)]

RecentArticle
A model of how the response from our api looks like. We would save this in a table called recent_articles in room database

Serializable means this whole entity or object can be passed as a byte stream to an activity or fragment (UI layer).

Okay, quick pause ⏸. Do you want to display ALL our data gotten from our remote data source to the user at once 🤔? 20,000 articles at once.? Do You?

Imagine if Instagram displays the whole photos of the 5,000 people you are following on your feed at once. (That will be horrible), why? → Your data gets consumed in one instance, you get to an almost never-ending loop of posts.

Solution:
Pagination
We will have to implement a mechanism of showing just the list of posts a user can consume on the screen at the moment.

As the user scrolls down→ We display more posts from our data source. That way, less data is consumed.

AllNewsRemotekey
We would save a reference to the next and previous pages of our response from our api in room database, call that table → all_news_remote_keys

Now lets see how we are going to query these items which we want to save and retrieve from the tables we have set up above

  • Under dao package create 2 new Kotlin File/Classes name them → ArticleDao and AllNewsRemoteKeysDao
  • Dao means — Data Access Object

ArticleDao

  • It is self explanatory → We want to Insert, Get, and Delete news articles into or from our database

AllNewsRemoteDao

Also self explanatory — Operations carried out on all_news_remote_keys table.

Repository

We are now at the repository layer (From fig 1).

Repository modules handle data operations.

They provide a clean API so that the rest of the app can retrieve this data easily. They know where to get the data from and what API calls to make when data is updated. You can consider repositories to be mediators between different data sources, such as persistent models, web services, and caches.

  • In data package, create 2 new Kotlin File/Class, call them → AllNewsRemoteMediator and AllNewsRepository

AllNewsRemoteMediator
What this class does is simple → Get data from the network and “incrementally” store them into local database (Room).
This is provided by the pagination library.

AllNewsRepository
Using flow and the remote mediator created above, we perform the operation of getting the news items (articles).

  • PagingConfig() defines how PagingSource should load the data.
  • pageSize Defines the number of items loaded at once from the PagingSource.
  • maxSize Defines the maximum number of items that may be loaded into PagingData before pages should be dropped.
  • prefetchDistance defines how far from the edge of loaded content an access must be to trigger further loading.
  • enablePlaceholders indicates whether you want to display placeholders when loading the data.

ViewModel

This is part of JetPack’s class which helps to store and manage UI related data in a very conscious way. → This way, even if you rotate your device, your data don’t get lost.
From the diagram in fig. 1 you would see that our ViewModel communicates with our Repository for storing and obtaining data.

  • Create a new package, Name that → viewmodel
  • Create a kotlin class/file, name that → AllNewsViewModel

AllNewsViewModel

  • Using hilt, we inject a reference to our repository
  • Create a function used to get recent news with returns a flow → of paginated articles data all cached in the context of a viewModelScope.

Activity/Fragment

Finally, we are at the top layer of fig.1 😌

This is where all the UI related stuff comes in place.
As you can see from the diagram, we only need to have a reference to our viewModel.

Our application makes use of a single activity which hosts our various fragments (Using navigation component).

  • Create a new package, call that → ui
  • In the ui package, create a new package, call that fragments
  • Inside fragments package, create a new fragment called HomeFragment

HomeFragment

  • First, set up your recycler view

As you can see, we bind our recyclerView adapter with our adapter.
One of them is used for displaying our paginated news (RecentNewsAdapter) while the other is used for handling retries when something wrong happens while loading the data (AllNewsLoadStateAdapter)

Please, check full code for:

- RecentNewsAdapter.kt

- LoadStateAdapter.kt

  • Next, we SAFELY collect our data (news article list)

Now, you have a well crafted, layered application with pagination and all the fancy new stuffs released and recommended by the android team (As at 8th, October, 2021 😏).

Thanks for reading!🤞

Contact Me
https://linktr.ee/Ibrajix

--

--