<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Ayush Bansal</title>
    <description>The latest articles on Forem by Ayush Bansal (@bansalayush).</description>
    <link>https://forem.com/bansalayush</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F399896%2Ffd0be76b-c362-45dc-acb2-7e6b9dbe30e8.jpeg</url>
      <title>Forem: Ayush Bansal</title>
      <link>https://forem.com/bansalayush</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/bansalayush"/>
    <language>en</language>
    <item>
      <title>ReverseProxy, API Gateway and Load Balancer</title>
      <dc:creator>Ayush Bansal</dc:creator>
      <pubDate>Tue, 10 Mar 2026 15:26:25 +0000</pubDate>
      <link>https://forem.com/bansalayush/reverseproxy-api-gateway-and-load-balancer-50ll</link>
      <guid>https://forem.com/bansalayush/reverseproxy-api-gateway-and-load-balancer-50ll</guid>
      <description>&lt;p&gt;TL;DR &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Forward Proxy&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Acts on behalf of the &lt;strong&gt;client&lt;/strong&gt; to access the internet.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Anonymity:&lt;/strong&gt; Hides the client’s IP address from the destination server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security &amp;amp; Filtering:&lt;/strong&gt; Blocks harmful sites and filters outgoing traffic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching:&lt;/strong&gt; Stores responses locally to save bandwidth for the internal network.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logging:&lt;/strong&gt; Monitors and records user activity within a private network.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Reverse Proxy&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Acts on behalf of &lt;strong&gt;servers&lt;/strong&gt; to manage incoming requests.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Server Anonymity:&lt;/strong&gt; Hides backend server details from the public.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSL Termination:&lt;/strong&gt; Handles CPU-intensive decryption/encryption.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compression:&lt;/strong&gt; Compresses responses (e.g., GZIP) to speed up delivery.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Traffic Inspection:&lt;/strong&gt; Scans for malicious code before it reaches the backend.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Load Balancer&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A specialized reverse proxy focused on &lt;strong&gt;traffic distribution&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Traffic Control:&lt;/strong&gt; Distributes requests across multiple servers to prevent overload.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reliability:&lt;/strong&gt; Ensures high availability by routing traffic away from failed servers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimization:&lt;/strong&gt; Maximizes performance across the entire server fleet.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. API Gateway&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;An API-aware proxy for managing &lt;strong&gt;microservices and web APIs&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Auth:&lt;/strong&gt; Centralizes authentication and authorization at the network edge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate Limiting:&lt;/strong&gt; Prevents abuse by capping request volume per client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transformation:&lt;/strong&gt; Converts protocols (e.g., JSON to XML) or modifies headers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Versioning:&lt;/strong&gt; Routes traffic to different service versions (v1 vs. v2).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring:&lt;/strong&gt; Tracks latency (P95) and usage analytics.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;References:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=DVR0zvDYJgY" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=DVR0zvDYJgY&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtu.be/xo5V9g9joFs?si=fgJcOx8u45kpow3l" rel="noopener noreferrer"&gt;https://youtu.be/xo5V9g9joFs?si=fgJcOx8u45kpow3l&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these &lt;strong&gt;sit between Client and the servers&lt;/strong&gt; . Each of these have a &lt;strong&gt;different purpose and solve different problems&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Before starting with Reverse Proxies let's understand what's a normal proxy (forward proxy) &lt;/p&gt;

&lt;h2&gt;
  
  
  Forward Proxy
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkxvci5b9ejclp0fqapc0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkxvci5b9ejclp0fqapc0.png" alt="Forward proxy" width="800" height="277"&gt;&lt;/a&gt;&lt;br&gt;
A forward proxy is a proxy server that sits in front of clients (users) and acts as a middleman between a private network and the public internet&lt;/p&gt;

&lt;p&gt;Its primary role is to help clients reach servers while providing a layer of control, security, or anonymity&lt;/p&gt;

&lt;p&gt;Key functions and characteristics of forward proxies include:&lt;br&gt;
&lt;strong&gt;Security and Filtering&lt;/strong&gt;: A forward proxy acts as a "guard" for a private network&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It can filter outgoing traffic to block harmful websites or scripts before they reach a user's machine&lt;/li&gt;
&lt;li&gt;Administrators can also blacklist specific websites to prevent employees or users from visiting them&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Anonymity&lt;/strong&gt;: It can be used as a privacy service to mask a client’s IP address&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In this scenario, the destination server only interacts with the proxy, not the actual client&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Caching for Performance&lt;/strong&gt;: Forward proxies can cache (store) responses locally&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For example, if one person in an office watches a specific tutorial video, the proxy saves a copy; when other people in the same office want to watch it, the proxy serves the cached version instead of downloading it again from the internet, which saves bandwidth and reduces traffic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Activity Logging&lt;/strong&gt;: They can be used to log user activity, allowing organizations to monitor which websites are being visited by people within the network&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Virus Scanning&lt;/strong&gt;: Beyond just blocking sites, a forward proxy can scan incoming responses for viruses and block malicious content before it enters the internal network&lt;/p&gt;




&lt;h2&gt;
  
  
  Reverse Proxy
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3sgygynbu8mrqqehgxu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3sgygynbu8mrqqehgxu.png" alt="Reverse Proxy" width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A reverse proxy is a proxy server that sits in front of one or more web servers, acting as an intermediary for incoming requests from clients.&lt;br&gt;
Unlike a forward proxy, which protects the user, a reverse proxy protects and manages the servers.&lt;br&gt;
When you visit a major website, you are typically communicating with a reverse proxy rather than the application server directly.&lt;br&gt;
Key functions and benefits of a reverse proxy include:&lt;br&gt;
&lt;strong&gt;Security and Anonymity&lt;/strong&gt;: It acts as a shield, hiding the existence and characteristics of the origin servers&lt;br&gt;
Because the proxy is the only entry point, attackers only see the proxy's IP address, keeping the actual backend servers hidden from the public internet&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SSL Termination&lt;/strong&gt;: Handling HTTPS encryption is CPU-intensive&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A reverse proxy can manage SSL/TLS decryption for all incoming traffic, freeing up the backend servers to focus on their primary tasks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Caching&lt;/strong&gt;: To speed up performance, a reverse proxy can store (cache) frequently requested content, such as images or videos&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If a thousand users request the same file, the proxy can serve it from its cache instead of reaching out to the backend every time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Compression&lt;/strong&gt;: It can compress outbound responses (using methods like GZIP) before sending them over the network to the client, which saves bandwidth&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Traffic Inspection&lt;/strong&gt;: Because it handles the requests first, it can scan for security threats, hacking attempts, or malicious code before the traffic ever reaches the internal network&lt;/p&gt;




&lt;h2&gt;
  
  
  Load Balancer
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgxqyxnv8xr3zr6ih6tl2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgxqyxnv8xr3zr6ih6tl2.png" alt="Load Balancers" width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A load balancer is a specialized type of reverse proxy whose primary mission is to distribute incoming network traffic across multiple backend servers. &lt;/p&gt;

&lt;p&gt;It acts as a traffic controller to ensure that no single server is overwhelmed, which optimizes the performance and reliability of an application&lt;/p&gt;




&lt;h2&gt;
  
  
  API Gateway
&lt;/h2&gt;

&lt;p&gt;An API gateway is a specialized, API-aware reverse proxy that sits between clients and backend services to manage, secure, and monitor APIs. While it shares some capabilities with load balancers and standard reverse proxies—such as forwarding and distributing traffic—its primary purpose is to handle the "cross-cutting concerns" required when exposing APIs to the outside world.&lt;/p&gt;

&lt;p&gt;Key functions of an API gateway include:&lt;br&gt;
&lt;strong&gt;Authentication and Authorization&lt;/strong&gt;: The gateway acts as a security checkpoint at the "edge" of the network.It validates tokens and checks permissions once, so that backend services do not have to duplicate this logic&lt;br&gt;
. Invalid or unauthorized requests are rejected before they ever reach the internal services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rate Limiting&lt;/strong&gt;: To prevent backend systems from being overwhelmed by intentional abuse or programming bugs, the gateway enforces limits on how many requests a client can make (e.g., 100 requests per minute).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request and Response Transformation&lt;/strong&gt;: The gateway can translate between different protocols or formats. For example, it might convert a client's JSON request into the XML format required by a legacy backend service, or strip sensitive internal fields from a response before it is sent back to the user&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;API Versioning&lt;/strong&gt;: It allows for smooth migrations by routing traffic to different versions of a service based on the URL (e.g., routing /v1/users to an old service and /v2/users to a new one).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analytics and Monitoring&lt;/strong&gt;: Because it sees all incoming traffic, the gateway can track which endpoints are most used, monitor latency (P95), and identify which clients are generating the most errors.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>devops</category>
      <category>networking</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Visualizing CompositionLocal in the Composition Tree</title>
      <dc:creator>Ayush Bansal</dc:creator>
      <pubDate>Thu, 05 Feb 2026 05:11:57 +0000</pubDate>
      <link>https://forem.com/bansalayush/visualizing-compositionlocal-in-the-composition-tree-2jkg</link>
      <guid>https://forem.com/bansalayush/visualizing-compositionlocal-in-the-composition-tree-2jkg</guid>
      <description>&lt;p&gt;Let me break this down with visual diagrams showing how data flows through the tree.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Composition Tree Structure
&lt;/h2&gt;

&lt;p&gt;When Compose runs your composables, it builds an internal tree structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your Code:                          Composition Tree:
─────────────                       ─────────────────
@Composable                         
fun App() {                              [App]
    Screen()          ───────►            │
}                                      [Screen]
                                          │
@Composable                            [Card]
fun Screen() {                            │
    Card()                             [Text]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. How CompositionLocal Attaches Data
&lt;/h2&gt;

&lt;p&gt;Think of each node having an &lt;strong&gt;optional "locals map"&lt;/strong&gt; attached:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Without CompositionLocalProvider:
─────────────────────────────────

     [App]                    ← locals: { }
       │
    [Screen]                  ← locals: { }
       │
     [Card]                   ← locals: { }
       │
     [Text]                   ← locals: { }


With CompositionLocalProvider:
──────────────────────────────

     [App]                    ← locals: { }
       │
  ┌────────────────────────────────────────────┐
  │ CompositionLocalProvider(LocalTheme → Dark)│
  └────────────────────────────────────────────┘
       │
    [Screen]                  ← locals: { LocalTheme → Dark }  ✓ ATTACHED HERE
       │
     [Card]                   ← locals: { }  (inherits from parent)
       │
     [Text]                   ← locals: { }  (inherits from parent)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. The Lookup Mechanism (Walking Up the Tree)
&lt;/h2&gt;

&lt;p&gt;When you call &lt;code&gt;LocalTheme.current&lt;/code&gt;, Compose walks &lt;strong&gt;UP&lt;/strong&gt; the tree until it finds a provider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;theme&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalTheme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;  &lt;span class="c1"&gt;// How does this work?&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LOOKUP: LocalTheme.current from [Card]
──────────────────────────────────────

     [App]          ← 4. Still not found? Use default or throw
       │
    [Screen]        ← 3. FOUND! LocalTheme → Dark ✓ RETURN THIS
       │                  (Provider attached here)
     [Card]         ← 2. Not here, look at parent...
       │
     [Text]         ← 1. Start here: "I need LocalTheme"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Shadowing with Nested Providers
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;CompositionLocalProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;LocalTheme&lt;/span&gt; &lt;span class="n"&gt;provides&lt;/span&gt; &lt;span class="nc"&gt;Dark&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Screen&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nc"&gt;CompositionLocalProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;LocalTheme&lt;/span&gt; &lt;span class="n"&gt;provides&lt;/span&gt; &lt;span class="nc"&gt;Light&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;AnotherScreen&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TREE WITH SHADOWING:
────────────────────

                    [App]
                      │
    ┌─────────────────────────────────────┐
    │  Provider(LocalTheme → Dark)        │
    └─────────────────────────────────────┘
                      │
         ┌────────────┴────────────┐
         │                         │
     [Screen]                 ┌─────────────────────────────┐
         │                    │ Provider(LocalTheme → Light)│ ← SHADOWS parent
     [Card]                   └─────────────────────────────┘
         │                              │
     [Text]                      [AnotherScreen]
                                        │
    LocalTheme.current               [Card]
         = Dark                         │
                                    [Text]

                                 LocalTheme.current
                                      = Light ← SHADOWED VALUE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Internal Data Structure (Simplified)
&lt;/h2&gt;

&lt;p&gt;Compose uses a &lt;strong&gt;Slot Table&lt;/strong&gt; - think of it as a flat array that mirrors the tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SLOT TABLE (simplified view):
─────────────────────────────

Index │ Node        │ Locals Map              │ Parent Index
──────┼─────────────┼─────────────────────────┼─────────────
  0   │ App         │ { }                     │ null
  1   │ Provider    │ { LocalTheme → Dark }   │ 0
  2   │ Screen      │ { }                     │ 1
  3   │ Card        │ { }                     │ 2
  4   │ Text        │ { }                     │ 3
  5   │ Provider    │ { LocalTheme → Light }  │ 1
  6   │ AnotherScr  │ { }                     │ 5
  7   │ Card        │ { }                     │ 6
  8   │ Text        │ { }                     │ 7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;*slot table is a topic in itself, don't be too hard on yourself to understand this&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lookup algorithm&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function lookup(key, nodeIndex):
    current = nodeIndex
    while current != null:
        if current.locals.contains(key):
            return current.locals[key]
        current = current.parentIndex
    return key.defaultValue  // or throw if no default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Visual: Multiple CompositionLocals
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;CompositionLocalProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;LocalTheme&lt;/span&gt; &lt;span class="n"&gt;provides&lt;/span&gt; &lt;span class="nc"&gt;Dark&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;LocalUser&lt;/span&gt; &lt;span class="n"&gt;provides&lt;/span&gt; &lt;span class="n"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;LocalAnalytics&lt;/span&gt; &lt;span class="n"&gt;provides&lt;/span&gt; &lt;span class="n"&gt;analyticsService&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    [App]
                      │
    ┌─────────────────────────────────────────────────────┐
    │  Provider                                           │
    │  locals: {                                          │
    │      LocalTheme     → Dark                          │
    │      LocalUser      → User(name="John")             │
    │      LocalAnalytics → AnalyticsServiceImpl          │
    │  }                                                  │
    └─────────────────────────────────────────────────────┘
                      │
                  [Content]
                      │
              ┌───────┴───────┐
              │               │
          [Header]        [Body]
              │               │
          [Avatar]        [Posts]

   LocalUser.current     LocalTheme.current
   = User("John")        = Dark
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. The "Recomposition Scope" Aspect
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WHEN VALUE CHANGES (compositionLocalOf):
────────────────────────────────────────

Provider(LocalCounter → 1)  ──changes to──►  Provider(LocalCounter → 2)
           │                                            │
       [Screen]  ← NOT recomposed                   [Screen]
           │       (doesn't read it)                    │
       [Counter] ← RECOMPOSED! ✓                   [Counter] ← reads LocalCounter
           │       (reads LocalCounter.current)        │
       [Label]   ← NOT recomposed                  [Label]
                   (doesn't read it)

Only nodes that actually READ the value get recomposed!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary Mental Model
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌──────────────────────────────────────────────────────────────┐
│                     COMPOSITION TREE                         │
│                                                              │
│   ┌─────┐                                                    │
│   │Node │ ◄─── Each node can have a "locals" attachment      │
│   └──┬──┘                                                    │
│      │      ┌──────────────────────┐                         │
│      │      │ locals: {            │                         │
│      │      │   Key1 → Value1      │ ◄── Provider attaches   │
│      │      │   Key2 → Value2      │     key-value pairs     │
│      │      │ }                    │                         │
│      │      └──────────────────────┘                         │
│   ┌──┴──┐                                                    │
│   │Child│ ◄─── Children inherit (lookup walks up the tree)   │
│   └─────┘                                                    │
│                                                              │
│   KEY INSIGHT: Data is NOT copied down.                      │
│   It's attached at one node, and lookups walk UP to find it. │
└──────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>jetpack</category>
      <category>android</category>
      <category>multiplatform</category>
    </item>
    <item>
      <title>ViewModel &amp; Co.</title>
      <dc:creator>Ayush Bansal</dc:creator>
      <pubDate>Mon, 26 May 2025 08:04:29 +0000</pubDate>
      <link>https://forem.com/bansalayush/viewmodel-co-gkh</link>
      <guid>https://forem.com/bansalayush/viewmodel-co-gkh</guid>
      <description>&lt;p&gt;Let's dive into the relationship between &lt;code&gt;ViewModel&lt;/code&gt;, &lt;code&gt;ViewModelProvider&lt;/code&gt;, &lt;code&gt;ViewModelStoreOwner&lt;/code&gt;, and &lt;code&gt;ViewModelStore&lt;/code&gt; by examining their roles and interactions within the AOSP codebase.&lt;/p&gt;

&lt;p&gt;Think of these four components working together as a system for managing and persisting UI data across configuration changes like screen rotations.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Core Components Explained
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. &lt;code&gt;ViewModel&lt;/code&gt; 🧠
&lt;/h4&gt;

&lt;p&gt;This is the class you'll interact with most directly. Its primary job is to &lt;strong&gt;hold and manage UI-related data&lt;/strong&gt;. The key feature of a &lt;code&gt;ViewModel&lt;/code&gt; is that it survives configuration changes that would normally destroy and recreate an &lt;code&gt;Activity&lt;/code&gt; or &lt;code&gt;Fragment&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When a &lt;code&gt;ViewModel&lt;/code&gt; is no longer needed (because its associated UI component is permanently destroyed), its &lt;code&gt;onCleared()&lt;/code&gt; method is called to free up any resources.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. &lt;code&gt;ViewModelStore&lt;/code&gt; 🗄️
&lt;/h4&gt;

&lt;p&gt;This is a simple container class. As its name suggests, its only job is to &lt;strong&gt;store &lt;code&gt;ViewModel&lt;/code&gt; instances&lt;/strong&gt;. Under the hood, it uses a &lt;code&gt;HashMap&amp;lt;String, ViewModel&amp;gt;&lt;/code&gt; to map a key (usually derived from the &lt;code&gt;ViewModel&lt;/code&gt;'s class name) to the &lt;code&gt;ViewModel&lt;/code&gt; instance itself.&lt;/p&gt;

&lt;p&gt;From the AOSP source, we can see its core implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// A simplified view from the source&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ViewModelStore&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ViewModel&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ViewModel&lt;/span&gt; &lt;span class="n"&gt;viewModel&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;ViewModel&lt;/span&gt; &lt;span class="n"&gt;oldViewModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mMap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;viewModel&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oldViewModel&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;oldViewModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onCleared&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ViewModel&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mMap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;clear&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ViewModel&lt;/span&gt; &lt;span class="n"&gt;vm&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;mMap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onCleared&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;mMap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;clear&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. &lt;code&gt;ViewModelStoreOwner&lt;/code&gt; 🧑‍💼
&lt;/h4&gt;

&lt;p&gt;This is an &lt;strong&gt;interface&lt;/strong&gt; that provides a &lt;code&gt;ViewModelStore&lt;/code&gt; to other objects. Any class that implements &lt;code&gt;ViewModelStoreOwner&lt;/code&gt; is responsible for two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Providing a &lt;code&gt;ViewModelStore&lt;/code&gt; via the &lt;code&gt;getViewModelStore()&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Retaining&lt;/strong&gt; that &lt;code&gt;ViewModelStore&lt;/code&gt; instance across configuration changes and calling its &lt;code&gt;clear()&lt;/code&gt; method when the scope is permanently destroyed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The most common implementers of this interface are &lt;strong&gt;&lt;code&gt;ComponentActivity&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;Fragment&lt;/code&gt;&lt;/strong&gt;. They handle the logic of saving and restoring the &lt;code&gt;ViewModelStore&lt;/code&gt; for you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The simple interface definition&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ViewModelStoreOwner&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@NonNull&lt;/span&gt;
    &lt;span class="nc"&gt;ViewModelStore&lt;/span&gt; &lt;span class="nf"&gt;getViewModelStore&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. &lt;code&gt;ViewModelProvider&lt;/code&gt; 🏭
&lt;/h4&gt;

&lt;p&gt;This is the &lt;strong&gt;factory and retriever&lt;/strong&gt; for &lt;code&gt;ViewModel&lt;/code&gt;s. You don't create &lt;code&gt;ViewModel&lt;/code&gt;s directly; you ask a &lt;code&gt;ViewModelProvider&lt;/code&gt; for one. It's responsible for either creating a new &lt;code&gt;ViewModel&lt;/code&gt; instance or, more importantly, retrieving an existing one from the &lt;code&gt;ViewModelStore&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When you create a &lt;code&gt;ViewModelProvider&lt;/code&gt;, you give it a &lt;code&gt;ViewModelStoreOwner&lt;/code&gt; (like an &lt;code&gt;Activity&lt;/code&gt; or &lt;code&gt;Fragment&lt;/code&gt;). The provider then uses the owner to get access to the &lt;code&gt;ViewModelStore&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// One of the main constructors&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;ViewModelProvider&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@NonNull&lt;/span&gt; &lt;span class="nc"&gt;ViewModelStoreOwner&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;@NonNull&lt;/span&gt; &lt;span class="nc"&gt;Factory&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getViewModelStore&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// The core 'get' method logic&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ViewModel&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;T&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@NonNull&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;@NonNull&lt;/span&gt; &lt;span class="nc"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;modelClass&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;ViewModel&lt;/span&gt; &lt;span class="n"&gt;viewModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mViewModelStore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Check the store first&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modelClass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viewModel&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ViewModel already exists, return it&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;viewModel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// ViewModel doesn't exist, create it using the factory&lt;/span&gt;
    &lt;span class="n"&gt;viewModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modelClass&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;mViewModelStore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;viewModel&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Put the new instance in the store&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;viewModel&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  The Relationship: How They Work Together
&lt;/h3&gt;

&lt;p&gt;Here's the step-by-step flow that connects all four components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Your &lt;strong&gt;&lt;code&gt;Activity&lt;/code&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;code&gt;Fragment&lt;/code&gt;&lt;/strong&gt; starts. Since it implements &lt;strong&gt;&lt;code&gt;ViewModelStoreOwner&lt;/code&gt;&lt;/strong&gt;, it either creates a new &lt;strong&gt;&lt;code&gt;ViewModelStore&lt;/code&gt;&lt;/strong&gt; or retrieves a previously saved one (if a configuration change just happened).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To get your &lt;code&gt;ViewModel&lt;/code&gt;, you instantiate a &lt;strong&gt;&lt;code&gt;ViewModelProvider&lt;/code&gt;&lt;/strong&gt;, passing your &lt;code&gt;Activity&lt;/code&gt;/&lt;code&gt;Fragment&lt;/code&gt; (&lt;code&gt;this&lt;/code&gt;) as the &lt;code&gt;ViewModelStoreOwner&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;&lt;code&gt;ViewModelProvider&lt;/code&gt;&lt;/strong&gt;'s constructor calls &lt;code&gt;getViewModelStore()&lt;/code&gt; on your &lt;code&gt;Activity&lt;/code&gt;/&lt;code&gt;Fragment&lt;/code&gt; to get a reference to the &lt;strong&gt;&lt;code&gt;ViewModelStore&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You call &lt;code&gt;viewModelProvider.get(MyViewModel.class)&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;&lt;code&gt;ViewModelProvider&lt;/code&gt;&lt;/strong&gt; asks the &lt;strong&gt;&lt;code&gt;ViewModelStore&lt;/code&gt;&lt;/strong&gt; if it already has an instance for the key associated with &lt;code&gt;MyViewModel&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;If yes&lt;/strong&gt;, the existing &lt;code&gt;ViewModel&lt;/code&gt; instance is returned. This is what happens during a screen rotation.&lt;br&gt;
&lt;strong&gt;If no&lt;/strong&gt;, the &lt;code&gt;ViewModelProvider&lt;/code&gt; uses its factory to create a new &lt;code&gt;MyViewModel&lt;/code&gt; instance, adds it to the &lt;strong&gt;&lt;code&gt;ViewModelStore&lt;/code&gt;&lt;/strong&gt;, and then returns it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When your &lt;code&gt;Activity&lt;/code&gt;/&lt;code&gt;Fragment&lt;/code&gt; is permanently destroyed (e.g., the user presses the back button and finishes it), its &lt;code&gt;ViewModelStoreOwner&lt;/code&gt; implementation calls &lt;code&gt;clear()&lt;/code&gt; on the &lt;strong&gt;&lt;code&gt;ViewModelStore&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;&lt;code&gt;ViewModelStore&lt;/code&gt;&lt;/strong&gt; then calls &lt;code&gt;onCleared()&lt;/code&gt; on every &lt;strong&gt;&lt;code&gt;ViewModel&lt;/code&gt;&lt;/strong&gt; it holds, allowing them to clean up their resources.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In essence, the &lt;strong&gt;&lt;code&gt;ViewModelStoreOwner&lt;/code&gt;&lt;/strong&gt; (the UI controller) owns the &lt;strong&gt;&lt;code&gt;ViewModelStore&lt;/code&gt;&lt;/strong&gt; (the storage). The &lt;strong&gt;&lt;code&gt;ViewModelProvider&lt;/code&gt;&lt;/strong&gt; (the factory) acts as the middleman to create or retrieve &lt;strong&gt;&lt;code&gt;ViewModel&lt;/code&gt;s&lt;/strong&gt; from that storage, ensuring you always get the correct instance for the given owner's lifecycle.&lt;/p&gt;

</description>
      <category>androiddev</category>
      <category>viewmodel</category>
    </item>
    <item>
      <title>Breaking the build 😝 : Demystifying Gradle</title>
      <dc:creator>Ayush Bansal</dc:creator>
      <pubDate>Wed, 30 Oct 2024 08:56:12 +0000</pubDate>
      <link>https://forem.com/bansalayush/breaking-the-build-demystifying-gradle-98g</link>
      <guid>https://forem.com/bansalayush/breaking-the-build-demystifying-gradle-98g</guid>
      <description>&lt;p&gt;As an Android developer, I've always been deep into coding and app design, but kind of skimmed over the whole Gradle thing—even though it's such a key part of our workflow. Recently, I decided to really get to know Gradle, and I want to share what I've learned. &lt;br&gt;
Let's break down some of its complexities and actually understand Gradle.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Understanding Settings file
&lt;/h3&gt;

&lt;p&gt;Let's get started by creating an empty project in Jetbrain's IntelliJ IDEA (Community Edition)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F899t3pmio93hfh97mayn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F899t3pmio93hfh97mayn.png" width="800" height="627"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The settings file, either &lt;code&gt;settings.gradle&lt;/code&gt; or &lt;code&gt;settings.gradle.kts&lt;/code&gt;, is the entry point of any Gradle project. Create a new file setting.gradle.kts. Your project structure should appear as follows&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu1gnbnzkc53x4hum787e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu1gnbnzkc53x4hum787e.png" width="800" height="532"&gt;&lt;/a&gt;&lt;br&gt;
Ignore other files for now&lt;/p&gt;
&lt;h4&gt;
  
  
  Key Components of the Settings File
&lt;/h4&gt;

&lt;p&gt;The settings file serves several purposes, but here are the three primary aspects to keep in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Naming Your Project:&lt;/strong&gt; 
Give your project a stable identifier using the &lt;code&gt;rootProject.name&lt;/code&gt; property.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;rootProject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"demo-project"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dependency and Plugins:&lt;/strong&gt; 
Specify where Gradle should look for other components your build may depend upon. There are two fundamentally different things:

&lt;ul&gt;
&lt;li&gt;The first thing are libraries your production code might need. e.g., an Apache Commons library.&lt;/li&gt;
&lt;li&gt;The second thing are plugins that extend Gradle itself.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are usually located in the Gradle plugin portal, google and mavenCentral but may also be provided through other binary repositories. Or, you may also define plugins locally in other builds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;dependencyResolutionManagement&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;repositories&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;google&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;mavenCentral&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;pluginManagement&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;repositories&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;gradlePluginPortal&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;google&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Structuring Your Project:&lt;/strong&gt; 
Organize your project into subprojects using the &lt;code&gt;include()&lt;/code&gt; function. This helps in managing separate components of your application.    e.g., we are defining 3 sub-projects "business-logic", "data-model", and "app".
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;include&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;":business-logic"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;include&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;":data-model"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;include&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;":app"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Based on the three points discussed, your &lt;code&gt;settings.gradle.kts&lt;/code&gt; file should be structured like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;rootProject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"demo-project"&lt;/span&gt;
&lt;span class="n"&gt;dependencyResolutionManagement&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;repositories&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;google&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;mavenCentral&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;pluginManagement&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;repositories&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;gradlePluginPortal&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;google&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;include&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;":business-logic"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;include&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;":data-model"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;include&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;":app"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The project structure, once the components are configured in the settings file, should appear as follows&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkzs94g6iufv0xlte60mx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkzs94g6iufv0xlte60mx.png" width="800" height="787"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Understanding Build Files
&lt;/h3&gt;

&lt;p&gt;We have created a project with three subprojects namely&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;business-login&lt;/li&gt;
&lt;li&gt;data-model&lt;/li&gt;
&lt;li&gt;app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So far, these subprojects are empty and thus have no real meaning to Gradle. We can add a build file to each of them to change this.&lt;/p&gt;

&lt;p&gt;The build file, either &lt;code&gt;build.gradle&lt;/code&gt; or &lt;code&gt;build.gradle.kts&lt;/code&gt;, is the heart of Gradle projects.&lt;br&gt;
These files are crucial as they dictate &lt;u&gt;how your project is built, what plugins and dependencies are included, and how your source code is organized&lt;/u&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  Key Components of the Build File
&lt;/h4&gt;

&lt;p&gt;Let's take a closer look at the build file for our business-logic  project. There are three things to configure in your build files.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Configuring Plugins:&lt;/strong&gt;
This is the first component in any build file. The plugins section provides structure by specifying the type of project you are building, enabling Gradle and your IDE to understand your project’s layout, compile options, and packaging details. Let’s clarify with an example. In this example, we’ll apply the Java Library Plugin.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;plugins&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"java-library"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Applying this plugin turns the subproject into a Java Library project, so Gradle and the IDE know where the source code is located, how the code is compiled, and how it’s packaged into a JAR file.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Setting Extension:&lt;/strong&gt;
Plugins often come with extensions that enable further customization. For the Java Library plugin, you can access the Java extension to configure compilation specifics, such as targeting a certain Java version.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;   &lt;span class="n"&gt;java&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
       &lt;span class="n"&gt;sourceCompatibility&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;JavaVersion&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;VERSION_11&lt;/span&gt;
       &lt;span class="n"&gt;targetCompatibility&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;JavaVersion&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;VERSION_11&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Defining Dependencies:&lt;/strong&gt;
Dependencies are what your subproject relies on for building and running. They can include other subprojects or external components housed in repositories. Here’s how you can define them:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;   &lt;span class="n"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
       &lt;span class="c1"&gt;// Dependency on internal subproject&lt;/span&gt;
       &lt;span class="n"&gt;implementation&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;":data-model"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
       &lt;span class="c1"&gt;// External library dependency&lt;/span&gt;
       &lt;span class="n"&gt;implementation&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"org.apache.commons:commons-lang3:3.12.0"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here, implementation is used to denote compile-time dependencies. The project keyword assists in referring to subprojects, while the external component is specified through its group, name, and version.&lt;/p&gt;

&lt;p&gt;Based on the three points discussed, your &lt;code&gt;business-logic/build.gradle.kts&lt;/code&gt; file should be structured like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;plugins&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"java-library"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;java&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;sourceCompatibility&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;gradle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;JavaVersion&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;VERSION_11&lt;/span&gt;
   &lt;span class="n"&gt;targetCompatibility&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;gradle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;JavaVersion&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;VERSION_11&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;implementation&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;":data-model"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
   &lt;span class="n"&gt;implementation&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"org.apache.commons:commons-lang3:3.12.0"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And Project structure should appear as follows&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhebwewfxj5jf9yp58cj0.png" width="800" height="279"&gt;
&lt;/h2&gt;

&lt;p&gt;Sharing my notes/project(which form the base of this and upcoming article/s) as github &lt;a href="https://github.com/bansalayush/demo-project-gradle" rel="noopener noreferrer"&gt;project&lt;/a&gt; . &lt;/p&gt;

&lt;p&gt;In our future discussions, we'll delve deeper into advanced Gradle features and plugins, further expanding development toolkit. Till then Keep exploring and building :🚀🚀!&lt;/p&gt;

</description>
      <category>gradle</category>
      <category>android</category>
      <category>androiddev</category>
      <category>kotlin</category>
    </item>
  </channel>
</rss>
