How I Built a Simple Currency Converter App — Using Recommended Android Pattern and Architecture
--
Hello, In this article, I will show you how to build a very simple currency converter app that lets you convert figures from one currency to another.
In this app, I carefully followed the clean architectural pattern — as recommended by the Android team.
This app uses —
- Kotlin
- MVVM (Model View ViewModel Pattern)
- Hilt (For Dependency Injection)
- An API to get currency rate and conversion (https://currency.getgeoapi.com/) (You can use any!)
- Retrofit (For making API calls)
- Flow
- LiveData
- Coroutines (For simplifying Asynchronous operations)
- View Binding (For interacting with views)
- Some other libraries
AND…NO — I didn't use Android Navigation Component — Its a single activity app 👽)
This is how the final app will look like
And this is a video showing how the app works
OKAY…LETS START CODING!!
STAGES
- Setting up Android studio
- Adding all the necessary dependencies
- Setting up Splash Screen
- Setting up required resources
- Building View/Layout
- Create Utility And Helper Classes
- Setting up Retrofit
- Setting up Hilt (Dependency Injection)
- Setting up Model
- Set up Repository and View Model
- Setting Up Activity
That was one hell of a list, I know! lets take them one by one and we’ll be done in no time. I promise 😐
SETTING UP ANDROID STUDIO
- I’ll assume you’ve already downloaded and installed android studio, if not click here — https://developer.android.com/studio?gclid=Cj0KCQiAlsv_BRDtARIsAHMGVSaAQQ9M4x_DtOVZosS5_4xa2i4RYCHuqzjFqQbAwHurV7m0RG1iPGcaApI4EALw_wcB&gclsrc=aw.ds
- Create a
New Project
— SelectEmpty Activity
— Name the project anything, I named mine “Direct Currency Converter
” — ClickFinish
ADDING ALL THE NECESSARY DEPENDENCIES
Before adding our dependencies, lets refractor our project structure by creating 6 packages. Right click on project package — New
— Package
. Name them — di
, helper
, model
, network
, view
and viewmodel
. After that, move MainActivity
to the view
package you just created
Your project should now look like this
Now open manifest — AndroidManifest.xml
file. Add the following permissions for accessing network because we need to be connected to the internet to make API calls.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
Okay lets add our dependecies
.
- Open
build.grade(app)
- Add the dependencies below (I added a comment to explain what each dependency does)
- Note — There are some dependencies I added which we may not use for this project (E.g Room, Glide). We may need them later on when updating the codebase or adding new feature such as
caching
etc
SETTING UP SPLASH SCREEN
A splash screen usually appears while an app is launching/loading.
Instead of showing a blank screen, we will show our app logo.
- Copy any image you want to use as the splash screen logo and paste it in the
drawable
directory. - Make sure you use a
png
image with a size of around114dp X 114dp
. I’d recommend you useBatch Drawable Import
for displaying appropriate images for different resolution. Search for that plugin and read on how to use it. - Now, create a new
drawable
resource file in thedrawable
directory — name itsplash_screen.xml
- Input the code below
- Navigate to
values
directory and openstyles.xml
file, we will add ourSplash Screen Theme
here - We will create our font directory later, so ignore the error
- In your
Manifest.xml
add the attributeandroid:theme=”@style/splashScreenTheme”
to yourMainActivity
<activity
android:name=".view.MainActivity"
android:theme="@style/splashScreenTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
- Finally, in your
view/MainActivity
class. InsideonCreate
method Beforesuper.onCreate
method, set the activity theme to yourapp theme
. Like this:-
override fun onCreate(savedInstanceState: Bundle?) {
//here
setTheme(R.style.AppTheme_NoActionBar);
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
SETTING UP REQUIRED RESOURCES
We will now set up resources such as strings, colors and font for our app.
- Open
colors.xml
- Paste this code there
- Open
strings.xml
and modify
- Right click on
res
directory, create a newAndroid Resource Directory
, name —font
, set Resource type —font
clickOk
. - Now go to https://fonts.google.com/ and download
Convergence
font, extract and paste thefont
in that directory — The directory should be like thisres/font/convergence.ttf
Yeaah!! 👏
BUILDING VIEW/LAYOUT
- Open
layout/activity_main.xml
- Paste the code below
- Create a new
drawable
, named —edit_text_input_with_border
(Used for styling the editText field) - Paste the following code
- Create another
drawable
— named —edit_text_input_with_border_2
- Paste the following code
- Finally, create the last
drawable
— namedbtn_main_round
(For styling theconvert
button) - Paste the following code
Our layout now looking set 😺
CREATE UTILITY AND HELPER CLASSES
These classes will help us handle network state, hide the keyboard in our activity, make status bar transparent and handle single live event, which is always aware of a view LifeCycle.
- Under
helper
package Create a newObject
calledUtiltity.kt
- Put the following code there
- Create a new class
EndPoints.kt
under the samehelper
package
class EndPoints {
companion object {
//Base URL const val BASE_URL = "https://api.getgeoapi.com/api/v2/currency/"
//API KEY - Go to geo currency converter website, obtain an API key and paste it between " "
const val API_KEY = " "
//COVERT URL
const val CONVERT_URL = "convert"
}
- In order to make this tutorial not extremely lengthy, I will urge you to take a look at the repo for this project and check out the other classes under the
helper
package
https://github.com/ibrajix/DirectCurrencyConverter
SETTING UP RETROFIT
Retrofit makes it very easy to consume RESTful
web services. Retrofit automatically serializes the JSON response using a POJO (Plain Old Java Object) which we will define in our data structure.
- Under the
network
package, create aninterface
named —ApiService.kt
- ApiService— This interface contains all the possible HTTP operations needed to be carried out, for our app we are simply making a GET request to our API with several parameters.
- Under the same package, create a new class called
ApiDataSource.kt
- This class exposes the
ApiService
interface so we can use it in our repository, which we will create later on.
- Create a class called —
BaseDataSource
- This class helps handle state of the request — either successful, failed or loading so we can perform appropriate actions or show appropriate error message.
SETTING UP HILT FOR DEPENDENCY INJECTION
- We have already added the dependency for hilt in
build.gradle(app)
- Navigate to
build.gradle(project)
- Inside the dependency block, add hilt class path, it should look like this
dependencies {
classpath "com.android.tools.build:gradle:4.0.2"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
//hilt for di
ext.hilt_version = '2.28-alpha'
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
- Create a new kotlin class inside the
di
package —MyApplication.kt
- We will annotate this class with
@HiltAndroidApp
— This will help us generate all the required hilt codes including a base class that serves as the application-level dependency container.
- Create another kotlin class under the same package, name it —
AppModule.kt
- This class is used to perform injection to types such as interfaces and classes from external libraries which we do not own. We will tell hilt how to provide instances of certain types.
- The code looks like this
- Update your
manifest.xml
. Addandroid:name=”.di.MyApplication”
to application block like this
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
//add this line
android:name=".di.MyApplication"
SETTING UP MODEL
let us create a data class for the Response
gotten from the server as POJO.
- Create 2 new classes under
model
package calledApiResponse
andRates
— Note you can automatically model your Json to kotlin data class using the Kotlin Data Class from Json Plugin - For
ApiResponse
, this is how the code looks
- For
Rates
, this is how the code looks like.Yours may be different depending on the type of Json data gotten from your API
SETTING UP REPOSITORY AND VIEWMODEL
- In your
viewmodel
package , create 2 new classes calledMainRepo
andMainViewModel
- MainRepo — This class interacts with our
ApiDataSource
which makes the network request. The data obtained from the request is emitted and returned as a flow which can then be collected in ourviewModel
which is ultimately observed in theView
.
- MainViewModel — This class interacts with the
repository
by collecting the data obtained from the request which can then be returned as Live Data for theMainActivity
View.
SETTING UP ACTIVITY
Finally, let us set up our activity, all we have to do is
- Initialize our view binding class and get a reference of all views in our layout
- Set up the logic for handling click events for the spinner — Country list item
- After inputting a value and hitting convert — Interact with the view model, observe the data and get the state of the request
- Depending on the state of the request — Perform necessary actions.
Here is the MainActivity
, all the codes, methods were properly documented and explained.
We have come to the end of the tutorial, I hope you’ve learnt a thing or two.
Here is a link to the full source code for this project —
https://github.com/ibrajix/DirectCurrencyConverter
Subsequently, I may add other features to this project. Features such as Caching, Adding countries flag, Implementing Search Feature etc.
Let me know what you think.
Thanks!
Reach Me