<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Abd Ur Rehman on Medium]]></title>
        <description><![CDATA[Stories by Abd Ur Rehman on Medium]]></description>
        <link>https://medium.com/@manikhan53?source=rss-556400c17aa6------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*Nk7Zady0rFBCgyC37cUMng.jpeg</url>
            <title>Stories by Abd Ur Rehman on Medium</title>
            <link>https://medium.com/@manikhan53?source=rss-556400c17aa6------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 16 May 2026 17:28:35 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@manikhan53/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Implementing Clean Architecture with GetX and MVVM in Flutter, adhering to SOLID principles]]></title>
            <link>https://medium.com/@manikhan53/implementing-clean-architecture-with-getx-and-mvvm-in-flutter-adhering-to-solid-principles-8487994b993a?source=rss-556400c17aa6------2</link>
            <guid isPermaLink="false">https://medium.com/p/8487994b993a</guid>
            <category><![CDATA[getx]]></category>
            <category><![CDATA[mvvm-architecture]]></category>
            <category><![CDATA[solid]]></category>
            <category><![CDATA[mvvm]]></category>
            <category><![CDATA[flutter]]></category>
            <dc:creator><![CDATA[Abd Ur Rehman]]></dc:creator>
            <pubDate>Fri, 07 Feb 2025 07:54:53 GMT</pubDate>
            <atom:updated>2025-02-07T08:20:36.881Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*m9HHA9ABEn6K81zVkZIJZQ.png" /></figure><p>In this article, we’ll dive deep into <strong>Clean Architecture</strong> and how it can be implemented in Flutter with <strong>GetX</strong> for state management. We’ll also discuss the <strong>MVVM (Model-View-ViewModel)</strong> design pattern and how it aligns with <strong>SOLID principles</strong>. By the end, you’ll understand how to organize your Flutter project using these techniques to ensure a scalable, maintainable, and testable app.</p><h3>What is Clean Architecture?</h3><p><strong>Clean Architecture</strong> is a software design philosophy that encourages organizing code so that the core business logic is independent of external frameworks, UI, and databases. Separating concerns makes the system easier to maintain, test, and scale.</p><h3>MVVM Design Pattern</h3><p>The <strong>MVVM (Model-View-ViewModel)</strong> design pattern is widely used in modern software development, especially with frameworks like Flutter. It separates the UI layer from the business logic, making the application more testable and maintainable.</p><ul><li><strong>Model</strong>: Represents the data structure of the application, typically coming from a database, API, or a local storage system.</li><li><strong>View</strong>: The UI layer, which listens to changes in the ViewModel and updates the UI accordingly.</li><li><strong>ViewModel</strong>: Acts as a middle layer between the View and Model. It processes the data from the Model and formats it for the View.</li></ul><h3>Implementing Clean Architecture with GetX and MVVM in Flutter</h3><p>In this guide, we’ll build a user registration page using <strong>Clean Architecture, GetX </strong>for state management<strong>, </strong>and the<strong> MVVM pattern</strong> while adhering to the <strong>SOLID </strong>principles.</p><h4>Setting Up the Project</h4><p>Before implementing, ensure your Flutter project includes the necessary dependencies. We’ll use <em>dio</em> for API calls, <em>getx</em> for state management, <em>dio_cache_interceptor</em> for caching responses, and <em>shared_prefrences</em> to store data locally.</p><pre>dependencies:<br>  flutter:<br>    sdk: flutter<br>  dio: ^5.8.0+1<br>  get: ^4.6.6<br>  dio_cache_interceptor: ^3.5.1<br>  shared_preferences: ^2.5.1</pre><h4>Folder Structure (Code organization)</h4><pre>lib/<br>│<br>├── common/                # Shared utilities, themes, constants<br>│<br>├── app/                  <br>│   ├── exceptions/        # Custom exception handling<br>│   ├── global_widgets/    # Reusable UI components<br>│   ├── middlewares/       # Route guards and middlewares<br>│   ├── models/            # Entity definitions (business models)<br>│   ├── modules/           # Feature-based segregation <br>│   │   ├── auth/          <br>│   │   │   ├── bindings/      # Dependency bindings<br>│   │   │   ├── controllers/   # State management using GetX<br>│   │   │   ├── services/      # Business logic and use cases<br>│   │   │   ├── views/         # UI components<br>│   │   │   ├── widgets/       # Reusable widgets on module level<br>│   │   ├── dashboard/        <br>│   │   ├── root/          # Root navigation &amp; app entry point<br>│   ├── providers/         # API services and data sources<br>│   ├── routes/            # Navigation and route management<br>│   ├── services/          # Global services (e.g., Auth, Storage)<br>│<br>├── main.dart              # Application entry point</pre><h4>1. Models (Entities)</h4><p>Models define the data structure and represent core business objects.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/671d6d7cbedb326c19450b1ed0ac22f5/href">https://medium.com/media/671d6d7cbedb326c19450b1ed0ac22f5/href</a></iframe><p>The <strong>Model</strong> serves as an abstract superclass from the artools package, offering utility methods like stringFromJson and boolFromJson to ensure safe and reliable JSON data extraction.</p><pre>abstract class Model {<br>  static String? stringFromJson(Map&lt;String, dynamic&gt; json, String attribute,<br>      {String? defaultValue}) {<br>    try {<br>      return json[attribute] != null<br>          ? json[attribute].toString()<br>          : defaultValue;<br>    } catch (e) {<br>      throw Exception(&#39;Error while parsing $attribute[$e]&#39;);<br>    }<br>  }</pre><h3>2. Services (Use Cases &amp; Providers)</h3><p>The <strong>Service Layer</strong> contains business logic and API handling.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/113665a13cb3d9839b886a1f5e173220/href">https://medium.com/media/113665a13cb3d9839b886a1f5e173220/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/056959d50d213c7e02258fc14f1800f3/href">https://medium.com/media/056959d50d213c7e02258fc14f1800f3/href</a></iframe><p>To ensure that our RegisterService is not tightly coupled with the ViewModel, we define an abstract class, AuthServicewhich the ViewModel expects as a dependency. This approach enables us to inject any implementation, such as any, MockService making the application more testable and scalable.</p><p>By following this design, we ensure flexibility, allowing it RegisterService to remain interchangeable and ViewModel independent of specific implementations. The service will be injected using GetBindings and seamlessly integrating it into our architecture.</p><p>Now, let’s take a quick look at two additional dependencies — UserService and DioClient—to understand their roles.:</p><h4>UserService</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8d8bb7e96497ab24adc2add7a69ee6ce/href">https://medium.com/media/8d8bb7e96497ab24adc2add7a69ee6ce/href</a></iframe><p>The GetxService runs in the background, ensuring access to the currently logged-in user.</p><p>A listener is attached to the main User object to track changes and automatically save updated information to <strong>Local Storage (Shared Preferences)</strong>.</p><h4>LocalStorageService</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f11d0e2c1283ecb8a01dd97338e9bdf2/href">https://medium.com/media/f11d0e2c1283ecb8a01dd97338e9bdf2/href</a></iframe><h4>DioClient</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/fdc66fd6c864045cabdf8b8d619e639b/href">https://medium.com/media/fdc66fd6c864045cabdf8b8d619e639b/href</a></iframe><p>This base class handles API requests, providing essential methods like GET, POST, PUT, and DELETE.</p><ul><li>It automatically attaches an <strong>API authorization token</strong> to every request using InterceptorWrapper, if available.</li><li><strong>Logs</strong> all requests and responses when running in <strong>debug mode</strong> via LogInterceptor.</li><li><strong>Caches</strong> responses using DioCacheInterceptor with default cache options unless explicitly overridden by the client.</li></ul><h3>3. ViewModel (Controllers in GetX)</h3><p>ViewModels manage UI state and interact with services.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/36275dc55d4f7d9490ca3d1194246188/href">https://medium.com/media/36275dc55d4f7d9490ca3d1194246188/href</a></iframe><p>This ViewModel manages the business logic and updates the UI in the main view. Let’s see how we integrate the controller into the GetX ecosystem.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/93498244629cc3912f0cbea8abbfd4ef/href">https://medium.com/media/93498244629cc3912f0cbea8abbfd4ef/href</a></iframe><pre>//app_pages.dart<br><br>class AppPages {<br>  static var INITIAL = Routes.REGISTER;<br><br>  static final routes = [<br>    GetPage(<br>      name: Routes.REGISTER,<br>      page: () =&gt; RegisterView(),<br>      binding: AuthBinding(),<br>    ),<br>  ];<br>}</pre><h3>4. Views (Presentation Layer)</h3><p>Views are UI components that react to state changes.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/82badeaef15cbe5fc0058dd095834d29/href">https://medium.com/media/82badeaef15cbe5fc0058dd095834d29/href</a></iframe><blockquote>The view code provided is just a reference and may not fully match the UI shown below. Please refer to the complete source code for accurate implementation.</blockquote><p>Here, we’ve utilized GetView to link this view with RegisterController. GetX automatically provides access to the controller keyword, allowing seamless interaction with the ViewModel.</p><p>You might also notice MyImagePicker, which is implemented as a mixin. Using mixins is a good practice to keep reusable functionalities separate, making them easy to include whenever needed using the with keyword.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*r8NgiGvc1J2BaDemK85RCw.gif" /></figure><p>Let’s see how this approach is adhering to SOLID principles:</p><p><strong>Single Responsibility Principle (SRP)</strong></p><p>Each class has a single responsibility (e.g., RegisterService for authentication, RegisterController for UI state management).</p><p><strong>Open/Closed Principle (OCP)</strong></p><p>The AuthService can be extended with new implementations without modifying existing code.</p><p><strong>Liskov Substitution Principle (LSP)</strong></p><p>Any implementation of AuthService can replace another without affecting the RegisterController.</p><p><strong>Interface Segregation Principle (ISP)</strong></p><p>The AuthService provides a focused interface for authentication rather than a monolithic one.</p><p><strong>Dependency Inversion Principle (DIP)</strong></p><p>RegisterController depends on an abstraction (AuthService), not a concrete implementation.</p><p>We achieve a well-structured, maintainable, and scalable Flutter application by following Clean Architecture, MVVM, and SOLID principles with GetX. This approach ensures clear separation of concerns, easy dependency management, and improved testability.</p><p>Would you like to see additional examples or modifications for your specific project? Let me know your thoughts!</p><p><a href="https://github.com/mani53-dev/getx_cleanarchitecture">Source Code</a></p><p>Give this story applause if you like it!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8487994b993a" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Websockets with GetX in Flutter]]></title>
            <link>https://medium.com/@manikhan53/websockets-with-getx-in-flutter-8ef4de4b91bd?source=rss-556400c17aa6------2</link>
            <guid isPermaLink="false">https://medium.com/p/8ef4de4b91bd</guid>
            <category><![CDATA[getx]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[socketio]]></category>
            <category><![CDATA[chat]]></category>
            <category><![CDATA[websocket]]></category>
            <dc:creator><![CDATA[Abd Ur Rehman]]></dc:creator>
            <pubDate>Tue, 29 Oct 2024 09:40:37 GMT</pubDate>
            <atom:updated>2024-10-29T09:50:18.440Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CEDQcRKkFW2fR8GrUswPsA.png" /></figure><p>In this example, we’ll create a demo chat application using GetX state management and WebSockets in Flutter. Let’s dive in!</p><h3>Socket Service</h3><h4>Establishing the connection:</h4><p>To begin with, we need to whip up a GetX service that will create a socket instance and connect to our trusty server. Think of it as setting up a cozy coffee date with your server — everyone loves a good connection!</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c7ae2fa63e477ab2706e22c48af88a8e/href">https://medium.com/media/c7ae2fa63e477ab2706e22c48af88a8e/href</a></iframe><h4>Registering the listeners:</h4><p>Next up, it’s time to register our listeners. These little champs will keep an ear out for various events coming from the server.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/25a89d761d043652197aad5271be19dd/href">https://medium.com/media/25a89d761d043652197aad5271be19dd/href</a></iframe><h4>Communicating with the Server:</h4><p>Now that we’ve established our connection and declared all the necessary events, it’s time to kick off communication with the server. We’ll be emitting some actions, and in return, the server will send back the events we’ve outlined. Think of it as a well-rehearsed dialogue where both sides know exactly what to say!</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ec1c7eb1abe10e76ccfa6bdbf5bcbf2f/href">https://medium.com/media/ec1c7eb1abe10e76ccfa6bdbf5bcbf2f/href</a></iframe><p>We’ve defined several key events to manage our communication with the server: isP_RoomExist, sendPMessage, and leavePrivateRoom. The isP_RoomExist event checks if a chat room exists. If it doesn’t, the server will create one and emit the privateUserJoined event, which we’ll be eagerly listening for.</p><p>The same logic applies to sendPMessage, where the server will respond with P_Message, allowing us to add the message to our list and display it on the screen. And just like that, you&#39;re ready to chat!</p><h3>Let’s Dive into the Controller!</h3><p>Now to create the main business logic for our chat app we need to define a GetX controller that would help our screen to send and show the messages in the chat.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f608cce77db110b046442379ffd0b95c/href">https://medium.com/media/f608cce77db110b046442379ffd0b95c/href</a></iframe><p>Now, we’ve set up several key variables for our chat screen, including currentUser, scrollController, chatMessages, messageController, selectedChat, and, of course, our crucial instance of socketService.</p><p>In the init method, we’ve initialized multiple listeners on our reactive variables from the socket service. These listeners will help us monitor changes in the chat, such as new messages arriving, the retrieval of chat messages, and handling any error events that may occur.</p><p>Next, we invoke a method from the socket service to connect the currently logged-in user to the chat room, ensuring to include the user ID of the person we’ve been chatting with.</p><p>Once we’ve successfully loaded the previous messages, we add them to the chatMessages array and programmatically scroll the screen to the bottom, ensuring the latest messages are now visible to the user.</p><p>Here’s how users can fire off new messages in the chat, clean up resources, and leave the room when closing the screen.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c64740e81b89960fce8c699e3db72440/href">https://medium.com/media/c64740e81b89960fce8c699e3db72440/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*jj_NDhWqaP4LGceYXhepHA.gif" /></figure><h3>The Main View:</h3><p>Here’s the code for the actual view that the users would see:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/80a4fece8d8a739c6e1c11eee0acf9a9/href">https://medium.com/media/80a4fece8d8a739c6e1c11eee0acf9a9/href</a></iframe><p>If you liked this, give a round of applause! that all…👏</p><p>Enjoy the complete source code <a href="https://github.com/mani53-dev/websockets_with_getx">here!</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8ef4de4b91bd" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>