Best practice (Modularization) - built entirely with Jetpack Compose and cutting-edge libraries like Coroutines, Flow, Hilt, Coil, etc.
This project is using Material 3 components, as well as the Compose navigation library. It also has an integrated Static Analysis tool (Detekt) and CI/CD pipeline (Github Actions) + web scraping using a python script.
- Jetpack Compose
- Hilt
- Retrofit (with a deserializer for another API)
- Coroutines
- Coil
- Detekt
- GitHub Actions
- Material 3
- Compose Navigation
-
I've used GitHub Actions, and Bitrise just to see different results from different platforms, and so far, IMO, GitHub Actions is nicer, Bitrise already has everything but I'd like to have some flexibility and write some scripts :)
-
There was an issue with the previous local rates API, from bonbast.com which I replaced that with a new strategy. I've used a new script to scrap the data with Github Actions and store it in a file called currencies.json. The script is available in the project.
device-2023-01-05-224942.mp4
I've used the best practices from Google's official repository NowInAndroid, and used Modularization to make the app more scalable and maintainable.
- The logic behind searching is to get the data only after the last character is entered (using
flatMapLatest()
flow operator). - For the home screen, I am planning to get some data from the server for showing on the LineChart, but for now, I am using dummy data.
- Unfortunately, the API doesn't provide the data for the
LineChart
, so I am using dummy data for now. - Iran (my home country) has been facing inflation for the last decade, and surprisingly, because of protests and the lack of management, the inflation rate is increasing day by day. So, I took the chance and put a logic for showing the rates in different currencies as Local Currency, with a refresh policy between Saturday to Thursday, and the rates will be updated every 5 minutes. For Friday, the rates will be retrieved from the previous day.
This section is for those who are interested in the implementation details.
I had to combine two flows into one to avoid unnecessary network calls and extra logics inside views. So here is how I did it:
The implementation is pretty simple. I am using the combine
operator to combine the two flows into
one. The combine
operator will emit a new [Rate] model after multiplying the two values. The logic
and code is available in
the GetRatesUseCaseImpl
class.
I am using Retrofit for making API calls, and I am using a custom deserializer for the local currency API. The problem that I faced at first was that the original API was not free so I had to use an already made API instead. Another problem was that the API was returning the data in a different format, something like this format:
{
"usd": {
"sell": 43000,
"buy": 42900
},
"eur": {
"sell": 45870,
"buy": 45720
}
}
It was pretty hard to deserialize the data, so I had to write a custom deserializer for it. The deserializer is basically converting all those three objects into a list of [LocalRate] objects. Here you can find the deserializer: CurrencyDeserializer
I am sure this is one of the major problems that all Android developers might face while
using GSON
and Retrofit
, so I hope this will help you.
For this project, I am using CoinCap API for rates, as well as This API for live Iranian exchange rates.
Also, I am using https://coinicons-api.vercel.app/api/icon/ for getting the icons of the coins.
The project is using GitHub Actions to build and test the app on every push and pull request on two devices. Also, it is using Renovate to keep the dependencies up to date.
The project is using Detekt for static code analysis, and it is using GitHub Actions to run the analysis on every push and pull request.
I also used Detekt formatter to format the code automatically which is somehow a wrapper for ktLint as well.
Please see: https://detekt.dev/docs/rules/formatting
- Add Offline first support
- Unit Tests
- Get data from Server for LineChart
- Add more features