A simple shopping/e-commerce app which will list products across different caregories. Users can Search, Filter based on categories, Sort based on different parameters. App will support phones & tablets above Android Lolipop (SDK 21). App is developed in MVVM architecture.
-
View layer: Responsive UI which will work alike in Phones & Tablets is developed with the help of jetpack compose libraries such as
navigation-compose
,compose.material3
& 3rd party libs like coil & compose-ratingbar. Responsiveness across different screen sizes & orientation is achived usingJetpack WindowMetricsCalculator
. -
Data layer: Data layer of this application is developed by leveraging
OkHttp
,Retrofit
,Dagger-Hilt
. -
State Management: State across app is handled using
ProductViewModel
, State holder in Compose & SavedStateHandle class.
-
OkHttp caching: Once the data is fetched for the first time, app will be able to show data in case of no or poor network conditions. This also helps to reduce network traffic since it getting the cached data. The data will cache for 10 days & this can be adjusted.
-
Caching of image with Coil library & use of placeholders: Use of placeholders enhance UI on loading images for the first time while caching ensure faster image loading for subsequent app sessions.
-
Avoid unnessary API calls: Since it's able to get all the product details & categories from
https://fakestoreapi.com/products
&https://fakestoreapi.com/products/categories
APIs respectively, I'm able to reduce the number of API calls and able to make use of already available data. This also helps to achive expected result with less development efforts.
-
App text color has a glitch & was not displaying in one of my POCO C31 device. And app was working fine on all other devices & emulators. The issue was with forced dark theming in Xiaomi/Poco devices. Finally able to resolve it by manipulating
forceDarkAllowed
in app theme. -
App was not performing well in case of poor network (slow loading & data loss). Solved this issue by enabling OkHttp caching.
Demo phone: download APK here
WindowMetricsCalculator:
val widthSizeClass = calculateWindowSizeClass(this).widthSizeClass
val isExpandedScreen = widthSizeClass == WindowWidthSizeClass.Expanded
Filter logic:
fun getFilteredList(
listOfProducts: List<ProductModel>,
filters: List<String>
): List<ProductModel> {
val productListWithFilter: List<ProductModel>
if (filters.isNotEmpty()) {
productListWithFilter = listOfProducts.filter { product ->
filters.any { filter ->
product.category == filter
}
}
} else {
productListWithFilter = listOfProducts
}
return productListWithFilter
}
Search logic:
fun getProductListWithSearchTerm(
listOfProducts: List<ProductModel>,
searchTerm: String
): List<ProductModel> {
val productListContainsSearchTerm: List<ProductModel>
if (searchTerm.isNotBlank()) {
productListContainsSearchTerm = listOfProducts.filter {
it.title.lowercase().contains(searchTerm.lowercase()) ||
it.category.lowercase().contains(searchTerm.lowercase())
}
} else {
productListContainsSearchTerm = listOfProducts
}
return productListContainsSearchTerm
}
Sort logic:
fun getSortedProductList(
listOfProducts: List<ProductModel>,
sortOption: String
): List<ProductModel> {
val sortedIntersectionList: List<ProductModel>
when (sortOption) {
SORT_RATING -> {
sortedIntersectionList = listOfProducts.sortedByDescending { it.rating.rate }
}
SORT_PRICE_LOW_TO_HIGH -> {
sortedIntersectionList = listOfProducts.sortedBy { it.price }
}
SORT_PRICE_HIGH_TO_HIGH -> {
sortedIntersectionList = listOfProducts.sortedByDescending { it.price }
}
else -> {
sortedIntersectionList = listOfProducts
}
}
return sortedIntersectionList
}
This can happen because:
- No products match the search term.
- When a filter is applied, search happens only in that category.
- Network issue & data is not cached.
Unit test was written with the help of the JUnit4 testing framework: ProductViewModelUnitTest.kt
- Tested across devices from Lollipop (SDK 21) to Android 14 (with the help of emulators).
- Tested in Pixel tablet (Android 14, emulator).
- Tested in Android 10 & Android 13 real devices (phones)
- Tried state management on both portrait & landscape orientations.
- Tested different combinations of filter, search & sorting options.
- Tested on poor & no network conditions.
The project can be developed into a complete E-commerce app.
- Login for users: Enable login for users & provide cart, whishlist facility. This can be achive by integration Google auth or OTP via firebase.
- Paginated data: Pagination can be integrate in get products API call with the help of Paging3 library & serve a large quantity of items.
- Unit test coverage also can be improved by adding more test case scenarios (success, fail & boundary cases).
Suggestions and improvements are welcome
Compose ratingbar for display rating stars
Jetpack WindowMetricsCalculator
Retrieve complex data when navigating