{"id":13339528,"url":"https://github.com/islamarr/MVI_Clean_Architecture","last_synced_at":"2025-03-11T14:31:35.482Z","repository":{"id":103910700,"uuid":"489705968","full_name":"islamarr/MVI_Clean_Architecture","owner":"islamarr","description":"🚀 Grid view List of pictures.","archived":false,"fork":false,"pushed_at":"2022-07-14T07:27:33.000Z","size":19208,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-10-24T02:30:09.198Z","etag":null,"topics":["clean-architecture","coroutines","hilt-dependency-injection","moshi-converter","mvi-architecture","navigation-component","retrofit2","state-flow","unit-testing","viewbinding"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/islamarr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-05-07T15:06:52.000Z","updated_at":"2024-02-05T13:08:18.000Z","dependencies_parsed_at":null,"dependency_job_id":"838ef9b3-d860-415e-8735-995e4097051b","html_url":"https://github.com/islamarr/MVI_Clean_Architecture","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/islamarr%2FMVI_Clean_Architecture","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/islamarr%2FMVI_Clean_Architecture/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/islamarr%2FMVI_Clean_Architecture/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/islamarr%2FMVI_Clean_Architecture/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/islamarr","download_url":"https://codeload.github.com/islamarr/MVI_Clean_Architecture/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243051871,"owners_count":20228283,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clean-architecture","coroutines","hilt-dependency-injection","moshi-converter","mvi-architecture","navigation-component","retrofit2","state-flow","unit-testing","viewbinding"],"created_at":"2024-07-29T19:20:21.572Z","updated_at":"2025-03-11T14:31:35.437Z","avatar_url":"https://github.com/islamarr.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MVI_Clean_Architecture_Sample\n\n![GitHub followers][60]     ![GitHub Repo stars][61]     ![GitHub forks][62]\n\nAbout this project\n--------------\n🚀 Grid view List of pictures. \n\n🛠 Simple implementation for MVI architecture pattern and Clean Architecture.\n\n🛠 Unit tests included with test coverage round 100% for dataSources, repositories, UseCases and ViewModels.\n\n🛠 SOLID principles.\n\n🛠 Standard Coding Style.\n\n🛠 Support Tablet screens.\n\n\nThe Business Details\n--------------\n- The application should have two screens:\n  * The first screen have one view with thumbnails of all available photos returned from API.\n  * When the user taps on one of the thumbnails, a second screen load to show the larger photo in the middle of the screen.\n- Image Urls should be edited by omitting the proxy part “m.mobile.de/yams-proxy/”, prepending “https://” \n  and appending “?rule=mo-640.jpg” for normal images or “?rule=mo-1600.jpg” for larger one.\n- Display a grid list with 2 columns in the portrait mode and 3 columns in the landscape mode.\n\n\nDemo\n--------------\n\n![demo][0]\n\n\nArchitecture pattern Used\n--------------\n\n[MVI][1]\n\n![architecture pattern][2]\n\n\nTesting Coverage\n--------------\n\n![Testing][3]\n\n\nLibraries \u0026 Tools Used\n--------------\n\n* [Foundation][4] - Components for core system capabilities, Kotlin extensions and support for\n  multidex and unit testing.\n* [Test][5] - An Android testing framework for unit and runtime UI tests.\n* [Architecture][10] - A collection of libraries that help you design robust, testable, and\n  maintainable apps. Start with classes for managing your UI component lifecycle and handling data\n  persistence.\n    * [View Binding][11] - To more easily write code that interacts with views. \n    * [Lifecycles][12] - Create a UI that automatically responds to lifecycle events.\n    * [Navigation][13] - Handle everything needed for in-app navigation.\n    * [ViewModel][14] - Store UI-related data that isn't destroyed on app rotations. Easily schedule\n      asynchronous tasks for optimal execution.\n    * [Repository][15] - A Module that handle data operations, You can consider repositories to be mediators between different data sources.\n    * [Retrofit][16] - A simple library that is used for network transaction.\n    * [Hilt][17]: For [dependency injection][18]\n    * [Kotlin Coroutines][19] For managing background threads with simplified code and reducing needs for callbacks.\n    * [Kotlin Flows][20] - A stream of data that can be computed asynchronously.\n    * [Glide][21] - For image loading.\n\n* Other tools/plugins   \n    * [Obfuscation, Code shrinking][30] - Obfuscation is to reduce your app size by shortening the names of the app’s classes, methods, and fields. Shrinking to make the app as small as possible.\n    * [Google material design][31] to build high-quality digital experiences for Android.\n    * [SonarLint plugin][32] - Static Code Analysis that identifies and helps you fix quality and security issues as you code.\n\nTechnical choices\n--------------\n\n**MVI vs MVVM**\n\n- A consistent state during the lifecycle of Views. \n- As it is unidirectional, Data flow can be tracked and predicted easily. \n- It ensures thread safety as the state objects are immutable.\n- Easy to debug, As we know the state of the object when the error occurred.\n- It's more decoupled as each component fulfills its own responsibility.\n- Testing the app also will be easier as we can map the business logic for each state.\n- [Read more][40]\n\n**RecyclerView vs listview**\n\n- In RecyclerView, it is mandatory to use ViewHolder pattern Which optimize the performance.\n- DiffUtil callback Which optimize the performance.\n\n**Activities vs Fragments**\n\n- I have used a single-activity architecture which allowed me to take full advantage of the Navigation component, which mean that a single activity that manages and host multiple fragments.\n- The fragment is more lite weight than Activity.\n- I also added simple animation in navigation between fragments.\n\n**Hilt vs Dagger2 vs Koin**\n\n- Hilt is built on top of the Dagger, and it comes with some advantages like simplify Dagger code and create a standard set of components and scopes to ease setup.\n- As this project is simple, Hilt is the best one. For more complex projects I will go with Dagger2 to avoid some limitation of hilt.\n- Hilt does not need factories for ViewModel, koin need.\n- Hilt generate the code in the compile time, while koin in runtime.\n\n**Coroutines vs RxJava**\n\n- Coroutines come with many advantages over RxJava, beside that it is Kotlin-friendly design pattern, it is: \n\t* Lightweight: You can run many coroutines on a single thread due to support for suspension.\n    * Fewer memory leaks: Use structured concurrency to run operations within a scope.\n    * Built-in cancellation support.\n    * Many Jetpack libraries include extensions that provide full coroutines support.\n\n**Retrofit vs Volley**\n\n- Retrofit has a well-designed structure.\n- Suspend function support.\n\n**Moshi vs GSON**\n\n- Moshi is a Kotlin-Friendly converter. \n- Moshi has better and more human-readable serialization failed messages.\n- Moshi has Code-gen adapter for Kotlin, This is great! With help of annotations, you make the Serialization/Deserialization much faster and bypass the old slow reflection method that Gson uses!\n\n\n**Glide**\n\n- Glide very effective for almost any case where you need to fetch, resize, cache and display a remote image.\n- Support thumbnail and placeholder which I needed in this project.\n\n\nWhat's next\n--------------\nWhile the project scale up, Some points should be considered: \n- Parent classes should be added for common used classes like ViewModels and Use Cases.\n- Analytics and tracking system should be implemented to provide insight on app usage and user engagement.\n- Caching mechanism should be added to reduce network calls and improve the performance.\n- Pagination should be handled from backend and client side.\n\n\nOther Projects\n--------------\n\n* [ShutterStock image list][50] - MVVM Sample.\n* [Recorder][51] - Another MVVM Sample.\n* [Prayer Now][52] - One of the projects I developed has 15+ Million downloads.\n* [Mn Ahyaha][53] - Side project I developed from scratch.\n\n\n[0]: https://github.com/islamarr/MVI_Clean_Architecture/blob/master/app/src/main/res/drawable/demo.gif\n[1]: https://cycle.js.org/model-view-intent.html\n[2]: https://github.com/islamarr/MVI_Clean_Architecture/blob/master/app/src/main/res/drawable/mvi_diagram.png\n[3]: https://github.com/islamarr/MVI_Clean_Architecture/blob/master/app/src/main/res/drawable/unit_test_coverage.png\n[4]: https://developer.android.com/jetpack/components\n[5]: https://developer.android.com/training/testing/\n\n[10]: https://developer.android.com/jetpack/arch/\n[11]: https://developer.android.com/topic/libraries/view-binding\n[12]: https://developer.android.com/topic/libraries/architecture/lifecycle\n[13]: https://developer.android.com/topic/libraries/architecture/navigation/\n[14]: https://developer.android.com/topic/libraries/architecture/viewmodel\n[15]: https://developer.android.com/topic/architecture/data-layer#create_the_repository\n[16]: https://square.github.io/retrofit\n[17]: https://developer.android.com/training/dependency-injection/hilt-android\n[18]: https://developer.android.com/training/dependency-injection\n[19]: https://developer.android.com/kotlin/coroutines\n[20]: https://developer.android.com/kotlin/flow\n[21]: https://bumptech.github.io/glide/\n\n[30]: https://developer.android.com/studio/build/shrink-code#obfuscate\n[31]: https://m3.material.io/\n[32]: https://www.sonarlint.org/\n\n[40]: http://hannesdorfmann.com/android/mosby3-mvi-1/\n\n[50]: https://github.com/islamarr/shutterstock_image_list\n[51]: https://github.com/islamarr/recorder\n[52]: https://play.google.com/store/apps/details?id=com.AppRocks.now.prayer\n[53]: https://play.google.com/store/apps/details?id=com.Ihsan.Ahyaha\n\n[60]: https://img.shields.io/github/followers/islamarr?style=social\n[61]: https://img.shields.io/github/stars/islamarr/MVI_Clean_Architecture?style=social\n[62]: https://img.shields.io/github/forks/islamarr/MVI_Clean_Architecture?style=social","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fislamarr%2FMVI_Clean_Architecture","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fislamarr%2FMVI_Clean_Architecture","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fislamarr%2FMVI_Clean_Architecture/lists"}