<?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: supriya shah</title>
    <description>The latest articles on Forem by supriya shah (@supriya_shah_1e9c3df6158c).</description>
    <link>https://forem.com/supriya_shah_1e9c3df6158c</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%2F3697774%2Fb2737369-ff20-4f52-b0ce-e08756278312.png</url>
      <title>Forem: supriya shah</title>
      <link>https://forem.com/supriya_shah_1e9c3df6158c</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/supriya_shah_1e9c3df6158c"/>
    <language>en</language>
    <item>
      <title>Jetpack Compose: remember vs rememberSaveable</title>
      <dc:creator>supriya shah</dc:creator>
      <pubDate>Mon, 23 Mar 2026 09:09:36 +0000</pubDate>
      <link>https://forem.com/supriya_shah_1e9c3df6158c/jetpack-compose-remember-vs-remembersaveable-131o</link>
      <guid>https://forem.com/supriya_shah_1e9c3df6158c/jetpack-compose-remember-vs-remembersaveable-131o</guid>
      <description>&lt;p&gt;Originally published on Medium:&lt;br&gt;
&lt;a href="https://medium.com/@supsabhi/jetpack-compose-remember-vs-remembersaveable-75ff37f8047e" rel="noopener noreferrer"&gt;https://medium.com/@supsabhi/jetpack-compose-remember-vs-remembersaveable-75ff37f8047e&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it is?When to Use? your beginner friendly guide&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine this: You’re filling out a login form on your Android app, typing your email and password carefully. Just as you’re about to hit submit, you accidentally rotate your phone. Poof! All your entered data disappears, and you have to start over. Frustrating, right?&lt;/p&gt;

&lt;p&gt;This common scenario highlights one of the most crucial concepts in modern Android development with Jetpack Compose: state management.&lt;/p&gt;

&lt;p&gt;When building Android apps with Jetpack Compose, managing state is one of the most important tasks you’ll encounter.&lt;/p&gt;

&lt;p&gt;Whether you’re a beginner just starting your journey in Compose or an experienced developer looking to deepen your understanding, mastering remember() and rememberSaveable() is essential to make apps UI interactive and responsive to user actions. Keeping track of UI information — like user inputs, button clicks, or toggle switches — ensures your app behaves reliably and smoothly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is “State” in Simple Terms?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Think of state as your app’s memory.In UI programming, state is just information your app needs to “remember” to correctly show the screen. For example:&lt;/p&gt;

&lt;p&gt;The current text in a search box.&lt;br&gt;
How many times a button has been clicked.&lt;br&gt;
Whether a switch is on or off.&lt;br&gt;
In a counter app, the current number is the state.&lt;br&gt;
In a shopping cart, the list of items and total price represent state.&lt;br&gt;
When this information changes, the UI updates to reflect it. &lt;strong&gt;Jetpack Compose&lt;/strong&gt; uses mutable state objects like mutableStateOf() to track these changes reactively.&lt;/p&gt;

&lt;p&gt;In short it’s any data that can change over time and affects what users see on their screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-world analogy:&lt;/strong&gt; &lt;em&gt;State is like the current page number in a book you’re reading. As you progress through the book (interact with your app), the page number (state) changes, and this determines what content you see.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In traditional Android development with XML layouts, managing state was complex and error-prone. Jetpack Compose revolutionizes this by making UI a function of state. When state changes, the UI automatically updates to reflect those changes.&lt;/p&gt;

&lt;p&gt;Recomposition is Compose’s way of updating the UI when state changes. Jetpack Compose UI functions can be called multiple times (this is called recomposition).Think of it as automatically redrawing parts of your screen when something changes. However, there’s a catch: during recomposition, local variables get reset to their initial values unless we use special state holders.&lt;/p&gt;

&lt;p&gt;Without remember, every time your UI recomposes, your variable would reset to its initial state, losing any user input or interaction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is remember()?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;remember() is a Compose function that stores a value in memory during composition and returns the same value across recompositions. It’s like giving your Composable function a short-term.It saves the state in a temporary bundle behind the scenes, so user input or important UI state remains even after an activity is recreated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is rememberSaveable()?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;rememberSaveable() is like remember() with superpowers. It not only stores values across recompositions but also survives configuration changes like screen rotation, theme changes, and even process death in some cases. rememberSaveable uses Android’s SavedStateHandle behind the scenes, storing state in a bundle, so it can survive these changes automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How It Differs from remember()&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The key difference lies in persistence:&lt;/p&gt;

&lt;p&gt;remember(): Survives recomposition only&lt;br&gt;
rememberSaveable(): Survives recomposition + configuration changes&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use remember() when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Temporary UI state&lt;/strong&gt;: Button pressed states, animation values, scroll positions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Derived state&lt;/strong&gt;: Calculated values that can be easily recomputed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance-critical scenarios&lt;/strong&gt;: High-frequency updates where serialization overhead matters&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Large objects&lt;/strong&gt;: Complex objects that don’t need to survive configuration changes&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use rememberSaveable() when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;User input&lt;/strong&gt;: Form fields, search queries, text input&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Important user progress&lt;/strong&gt;: Game scores, shopping cart contents&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;User preferences&lt;/strong&gt;: Selected options, filter settings&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Navigation state&lt;/strong&gt;: Selected tabs, current page indices&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not managing state correctly can lead to frustrating UX, where your app forgets what the user was doing,your UI becomes essentially broken. Variables reset on every recomposition, and changes don’t trigger UI updates.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;One of the common misconception: “My composable only runs once.” In reality, composables can recompose many times.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Always assume your composable function will be called multiple times. That’s why below best practices are very much important&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;State hoisting&lt;/strong&gt;: Keep state at the lowest common parent&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Single source of truth&lt;/strong&gt;: Don’t duplicate state across composables&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Immutable state&lt;/strong&gt;: Use immutable data classes when possible&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoid side effects in composition&lt;/strong&gt;: Use LaunchedEffect or DisposableEffect&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Test configuration changes&lt;/strong&gt;: Always test your app by rotating the device&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Pro tip: For large datasets, save only the essential identifier (like a selected ID) in rememberSaveable() and recreate the full object using remember().&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Below is a Simple Example Showing the Difference&lt;/strong&gt;&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;WithoutRememberExample&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;onValueChange&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Type something"&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;p&gt;Here, every time Composable redraws (recomposes), text gets reset to empty, so any input is lost immediately — even when you type a character. The UI isn’t interactive at all because it never “remembers” what you typed.&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;RememberExample&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;text&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;remember&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;onValueChange&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Type something"&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;p&gt;Here the typed text is remembered only when the UI updates.&lt;/p&gt;

&lt;p&gt;But if you rotate the screen, text will reset to empty.&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;RememberSaveableExample&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;text&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;rememberSaveable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;mutableStateOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;onValueChange&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Type something"&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;p&gt;Here, text will still hold after device rotation or UI recreation.&lt;/p&gt;

&lt;p&gt;Understanding the difference between remember() and rememberSaveable() is crucial for building robust, user-friendly Android applications.Remember, becoming proficient with Compose state management takes practice.Start with simple examples and you will reach there sooner.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;👏 Found this helpful?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If this article helped you understand Jetpack Compose state management, please give it a clap and follow me for more Android development tutorials!&lt;/p&gt;

&lt;p&gt;💬 Questions or suggestions? Drop a comment below — I read and respond to every one!&lt;/p&gt;

&lt;p&gt;🔄 Share this article with fellow Android developers who might find it useful.&lt;/p&gt;

&lt;p&gt;Happy coding! 🚀&lt;/p&gt;

</description>
      <category>android</category>
      <category>mobile</category>
      <category>programming</category>
      <category>performance</category>
    </item>
    <item>
      <title>Lazy Grids in Jetpack Compose</title>
      <dc:creator>supriya shah</dc:creator>
      <pubDate>Tue, 17 Mar 2026 05:43:46 +0000</pubDate>
      <link>https://forem.com/supriya_shah_1e9c3df6158c/lazy-grids-in-jetpack-compose-4973</link>
      <guid>https://forem.com/supriya_shah_1e9c3df6158c/lazy-grids-in-jetpack-compose-4973</guid>
      <description>&lt;p&gt;Originally published on Medium: &lt;br&gt;
&lt;a href="https://medium.com/@supsabhi/lazy-grids-in-jetpack-compose-8a80f52421c9" rel="noopener noreferrer"&gt;https://medium.com/@supsabhi/lazy-grids-in-jetpack-compose-8a80f52421c9&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🧩 Mastering Grids in easy way&lt;/strong&gt;&lt;br&gt;
Ever opened an app and felt overwhelmed by a long, never-ending list? Or maybe you’ve needed to show a bunch of beautiful photos or product cards without cramming them into a tiny space?&lt;/p&gt;

&lt;p&gt;You know, the ones that scroll vertically and show these items one after another. But what if you want to show these items side by side, like a gallery, product catalog, or contact cards?&lt;/p&gt;

&lt;p&gt;That’s where the mighty Grid Layout comes in to save the day!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🏛 Classic Android Grids&lt;/strong&gt;&lt;br&gt;
In classic Android (XML days), developers often used:&lt;/p&gt;

&lt;p&gt;GridLayout or RecyclerView with GridLayoutManager for arranging UI components&lt;br&gt;
GridView for bigger, scrollable lists — like image thumbnails or product tiles in shopping apps&lt;br&gt;
💡 So… what exactly is a Grid Layout?&lt;br&gt;
A Grid is like a shelf with rows and columns.&lt;br&gt;
It’s a way to organize items into rows and columns so everything is neat, tidy, and easy to find.&lt;/p&gt;

&lt;p&gt;We use grid layouts whenever we need to display a collection of items that are:&lt;/p&gt;

&lt;p&gt;Visually Similar — Like a gallery of product images or thumbnails&lt;br&gt;
Equal in Importance — Unlike a news feed where the top item is most important, items in a grid usually hold similar weight&lt;br&gt;
High in Quantity — It’s a much better use of screen space than a vertical list when you have dozens of things to show&lt;br&gt;
⚡ Jetpack Compose Grids Got Lazy!&lt;br&gt;
In Jetpack Compose, there are mainly two ways to arrange items:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. GridLayout&lt;/strong&gt;&lt;br&gt;
Good for static, small-to-medium datasets&lt;br&gt;
Builds the whole UI upfront, so if you have a lot of items, it may slow things down&lt;br&gt;
Best for forms or dashboards where all elements should be shown at once&lt;br&gt;
No built-in “lazy loading” here&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Lazy Lists &amp;amp; Lazy Grids&lt;/strong&gt;&lt;br&gt;
Smart approach — only composes what’s visible on screen&lt;br&gt;
Includes LazyColumn (for vertical lists) and LazyVerticalGrid (for grids)&lt;br&gt;
Only creates as many views as fit on the screen plus a few extra for smooth scrolling&lt;br&gt;
Fast and memory-friendly, especially for huge lists&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🧠 LazyList vs LazyGrid — When to Use What?&lt;/strong&gt;&lt;br&gt;
Both LazyLists and LazyGrids are “lazy” because they only load the items currently visible on screen, saving battery and memory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🪄 LazyList (LazyColumn, LazyRow)&lt;/strong&gt;&lt;br&gt;
Displays items one after another (vertically or horizontally)&lt;br&gt;
Shows sequential content, so each item takes one entire row or column&lt;br&gt;
Perfect for feeds, chat screens, or any single-column list&lt;br&gt;
&lt;strong&gt;🧩 LazyGrid (LazyVerticalGrid, LazyHorizontalGrid)&lt;/strong&gt;&lt;br&gt;
Displays items in rows and columns, forming a neat grid layout&lt;br&gt;
Shows content in a collection manner, so each item takes up one cell in the grid&lt;br&gt;
Perfect for e-commerce product grids, image galleries, or dashboards&lt;br&gt;
🧰 Types of Grids in Jetpack Compose&lt;br&gt;
Jetpack Compose provides two main grid types out of the box:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LazyVerticalGrid&lt;/strong&gt;&lt;br&gt;
Scrolls vertically, items arranged in columns&lt;br&gt;
Think of your phone’s photo gallery&lt;br&gt;
LazyHorizontalGrid&lt;/p&gt;

&lt;p&gt;Scrolls horizontally, items arranged in column&lt;br&gt;
Also great for galleries or horizontally scrolling product carousels&lt;br&gt;
Both work exactly like LazyColumn or LazyRow, but with the magic of multiple columns or rows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🚀 Quick Example: LazyVerticalGrid&lt;/strong&gt;&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="nc"&gt;LazyVerticalGrid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GridCells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Fixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 3 columns&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Item $index"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&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;p&gt;columns = GridCells.Fixed(3) → We’re asking for 3 fixed columns&lt;br&gt;
Want an adaptive grid that fits as many columns as possible with at least 100dp width?&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="nc"&gt;LazyVerticalGrid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;columns&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GridCells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Adaptive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minSize&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&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="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Adaptive $index"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Modifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dp&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;p&gt;&lt;strong&gt;🧩 GridCells Properties — The Secret Sauce&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The real power of LazyVerticalGrid lies in how you define its columns using the GridCells object.&lt;/p&gt;

&lt;p&gt;Here are the main ways:&lt;/p&gt;

&lt;p&gt;GridCells.Fixed(count) — Sets an exact number of columns. Use when you always want, say, 3 columns, no matter the screen size (great for photo galleries)&lt;br&gt;
GridCells.Adaptive(minSize) — Creates as many columns as will fit, ensuring each column is at least a certain size. Makes your grid responsive across devices&lt;br&gt;
GridCells.FixedSize(size) — Sets an exact width for each column and fills the screen. Less common, but useful for rigid layouts&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🏁 Final Thoughts&lt;/strong&gt;&lt;br&gt;
Lazy Grids in Jetpack Compose are a total game-changer for displaying items in a flexible, scrollable grid — without dealing with RecyclerView adapters or XML layouts.&lt;/p&gt;

&lt;p&gt;They’re powerful, adaptive, and super easy to use. Once you try them, you’ll never want to go back.&lt;/p&gt;

&lt;p&gt;So go ahead — build that gallery, product grid, or dashboard with LazyVerticalGrid and let Compose handle the heavy lifting! 🚀&lt;/p&gt;

&lt;p&gt;Grid layouts are everywhere in Android, and Jetpack Compose’s Lazy grids make building them for modern apps super easy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💡 Detailed source code and more Compose examples are available on my GitHub — check it out and explore!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/supsabhi/GridLayoutDemo.git" rel="noopener noreferrer"&gt;https://github.com/supsabhi/GridLayoutDemo.git&lt;/a&gt;&lt;/p&gt;

</description>
      <category>android</category>
      <category>mobile</category>
      <category>jetpack</category>
      <category>development</category>
    </item>
    <item>
      <title>Build a Cross-Platform QR Code Scanner in .NET MAUI using ZXing.Net.MAUI</title>
      <dc:creator>supriya shah</dc:creator>
      <pubDate>Fri, 06 Feb 2026 07:12:32 +0000</pubDate>
      <link>https://forem.com/supriya_shah_1e9c3df6158c/build-a-cross-platform-qr-code-scanner-in-net-maui-using-zxingnetmaui-5993</link>
      <guid>https://forem.com/supriya_shah_1e9c3df6158c/build-a-cross-platform-qr-code-scanner-in-net-maui-using-zxingnetmaui-5993</guid>
      <description>&lt;p&gt;Originally published on Medium:&lt;br&gt;
&lt;a href="https://medium.com/@supsabhi/build-a-cross-platform-qr-code-scanner-in-net-maui-using-zxing-net-maui-5638b479372d" rel="noopener noreferrer"&gt;https://medium.com/@supsabhi/build-a-cross-platform-qr-code-scanner-in-net-maui-using-zxing-net-maui-5638b479372d&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A step-by-step beginner’s guide to integrating QR and barcode scanning easily in your MAUI app&lt;/strong&gt;&lt;br&gt;
If you want to build a &lt;strong&gt;cross-platform app with QR code scanning in .NET MAUI&lt;/strong&gt;, there are several ways to do it. You can use libraries like &lt;strong&gt;ZXing.Net.Maui.Controls, Camera.MAUI, IronQR, or Google Vision ML Kit.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each has its own strengths:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;- &lt;strong&gt;ZXing&lt;/strong&gt; is open-source and widely adopted.&lt;/li&gt;
&lt;li&gt;- &lt;strong&gt;IronQR&lt;/strong&gt; offers a simple and commercial-ready cross-platform library.&lt;/li&gt;
&lt;li&gt;- &lt;strong&gt;Google Vision ML Kit&lt;/strong&gt; provides a machine learning–based alternative.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But today, we’ll focus on &lt;strong&gt;ZXing.Net.MAUI&lt;/strong&gt;, one of the most popular and developer-friendly options.&lt;/p&gt;

&lt;p&gt;In this guide, you’ll learn &lt;strong&gt;everything you need&lt;/strong&gt; to integrate &lt;strong&gt;ZXing QR Code Scanner&lt;/strong&gt; in .NET MAUI — including installation, initialization, permissions, and a working example with XAML and C# code.&lt;br&gt;
We’ll also cover &lt;strong&gt;useful options&lt;/strong&gt; like torch and scan area, &lt;strong&gt;common issues&lt;/strong&gt;, and testing tips.&lt;/p&gt;

&lt;p&gt;🧩 &lt;strong&gt;Why Choose ZXing for .NET MAUI?&lt;/strong&gt;&lt;br&gt;
There are plenty of reasons developers prefer ZXing.Net.MAUI when adding barcode or QR code scanning features to their apps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Open-source and widely used&lt;/strong&gt; — trusted by many developers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supports multiple barcode types&lt;/strong&gt; — QR, EAN, Code128, PDF417, and more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Works across platforms&lt;/strong&gt; — Android, iOS, and Windows (WinUI).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Includes both live camera scanning and image decoding.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy to integrate and customize&lt;/strong&gt; — choose barcode formats, enable torch, or adjust detection options.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Actively maintained and community&lt;/strong&gt;-supported, ensuring stability and updates.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;⚙️ 1. &lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;br&gt;
Before diving in, make sure you have the following ready:&lt;/p&gt;

&lt;p&gt;✅ The latest &lt;strong&gt;.NET SDK *&lt;em&gt;(recommended *&lt;/em&gt;.NET 8&lt;/strong&gt;)&lt;br&gt;
✅ &lt;strong&gt;Visual Studio 2022&lt;/strong&gt; or later with the Mobile development with .NET workload installed&lt;br&gt;
✅ A working &lt;strong&gt;.NET MAUI project&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you’re new to MAUI, open Visual Studio → Create New Project → choose .NET MAUI App.&lt;/p&gt;

&lt;p&gt;📦 2.&lt;strong&gt;Installation&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Step 1: Install the ZXing.Net.MAUI NuGet Package&lt;/strong&gt;&lt;br&gt;
Think of a NuGet package as a toolbox that adds new features to your app.&lt;br&gt;
To enable QR scanning, install the ZXing.Net.Maui.Controls package.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 1 — Using CLI:&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;dotnet add package ZXing.Net.Maui.Controls --version 0.4.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Option 2 — Using Visual Studio:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Right-click on your &lt;strong&gt;.NET MAUI project&lt;/strong&gt; in Solution Explorer.&lt;/li&gt;
&lt;li&gt;Select Manage &lt;strong&gt;NuGet Packages&lt;/strong&gt;…&lt;/li&gt;
&lt;li&gt;Go to the &lt;strong&gt;Browse&lt;/strong&gt; tab and search for &lt;strong&gt;ZXing.Net.Maui.Controls&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Install&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;This gives you access to ready-to-use UI controls such as the camera scanner view.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Initialize ZXing in MauiProgram.cs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your MAUI app needs to know that ZXing is part of the project. You do this by registering the barcode reader service in MauiProgram.cs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
using ZXing.Net.Maui;
public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp&amp;lt;App&amp;gt;()
            .UseBarcodeReader(); // register ZXing
        return builder.Build();
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 Note: Depending on the package version, you may need to use&lt;br&gt;
.UseZXingNetMaui() instead of .UseBarcodeReader().&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Add Camera Permissions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Since scanning requires camera access, your app must request permissions or it’ll show a black screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔹 Android&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Edit Platforms/Android/AndroidManifest.xml:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;uses-permission android:name="android.permission.CAMERA" /&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Android 6.0 (API 23) and above, request permission at &lt;strong&gt;runtime&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;var status = await Permissions.RequestAsync&amp;lt;Permissions.Camera&amp;gt;();
if (status != PermissionStatus.Granted)
{
    // Handle permission denied
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;🔹 iOS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open Platforms/iOS/Info.plist and add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;key&amp;gt;NSCameraUsageDescription&amp;lt;/key&amp;gt;
&amp;lt;string&amp;gt;This app uses the camera to scan QR codes.&amp;lt;/string&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you plan to scan images from the gallery, also add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;key&amp;gt;NSPhotoLibraryUsageDescription&amp;lt;/key&amp;gt;
&amp;lt;string&amp;gt;This app accesses your photo library to scan QR codes from images.&amp;lt;/string&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;🔹 Windows (WinUI)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Edit &lt;code&gt;Package.appxmanifest&lt;/code&gt; and enable Webcam under Capabilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🎥 3. Create the Scanner UI in XAML&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now let’s design the UI. ZXing provides a CameraBarcodeReaderView control for real-time scanning.&lt;/p&gt;

&lt;p&gt;Open your XAML page (e.g., ScannerPage.xaml) and add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;
&amp;lt;ContentPage
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:zxing="clr-namespace:ZXing.Net.Maui;assembly=ZXing.Net.MAUI"
    x:Class="MyMauiApp.Pages.ScannerPage"&amp;gt;
&amp;lt;Grid RowDefinitions="*,Auto" Padding="10"&amp;gt;
        &amp;lt;!-- Camera scanner view --&amp;gt;
        &amp;lt;zxing:CameraBarcodeReaderView 
                        x:Name="cameraView"
                        BarcodesDetected="CameraView_BarcodeDetected"
                        IsScanning="True"
                        IsTorchOn="False"
                        IsDetecting="True"
                        VerticalOptions="FillAndExpand" 
                  /&amp;gt;
        &amp;lt;!-- Result Label --&amp;gt;
            &amp;lt;StackLayout Grid.Row="1" 
             Orientation="Horizontal" 
              HorizontalOptions="Center"&amp;gt;
            &amp;lt;Label x:Name="ResultLabel"
            Text="No code scanned yet" 
            VerticalOptions="Center" /&amp;gt;
        &amp;lt;/StackLayout&amp;gt;
    &amp;lt;/Grid&amp;gt;
&amp;lt;/ContentPage&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;x:Name="cameraView" → gives a name to access it in C#.&lt;/li&gt;
&lt;li&gt;IsDetecting="True" → enables live scanning.&lt;/li&gt;
&lt;li&gt;BarcodesDetected="CameraView_BarcodeDetected" → triggers when a QR code is found.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;💻 4. Handle Scanned Results in Code-Behind&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open the code-behind file (ScannerPage.xaml.cs) and implement your scan logic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using ZXing.Net.Maui;
using ZXing.Net.Maui.Controls;
public partial class ScannerPage : ContentPage
{
    bool _isProcessing = false;
    public ScannerPage()
    {
        InitializeComponent();
    }
    private void CameraView_BarcodeDetected(object sender, BarcodeDetectionEventArgs e)
    {
        var result = e.Results?.FirstOrDefault();
        if (result == null) return;
        if (_isProcessing) return;
        _isProcessing = true;
        MainThread.BeginInvokeOnMainThread(async () =&amp;gt;
        {
            cameraView.IsDetecting = false;
            ResultLabel.Text = result.Value ?? "Empty";
            await DisplayAlert("Scanned", result.Value, "OK");
            // Resume scanning if needed
            cameraView.IsDetecting = true;
            _isProcessing = false;
        });
    }
    protected override void OnDisappearing()
    {
        base.OnDisappearing();
        cameraView.IsDetecting = false;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;🛠️ 5. Common Problems &amp;amp; Fixes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Black Screen or Blank Preview&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Usually caused by missing camera permission.&lt;/li&gt;
&lt;li&gt;Always check and request permissions at runtime.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;No Barcode Detected&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check lighting conditions or camera focus.&lt;/li&gt;
&lt;li&gt;Move the device closer to the QR code.&lt;/li&gt;
&lt;li&gt;Ensure IsDetecting="True" is set.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;⚡ Optimize Scanning Performance&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Restrict formats for faster detection:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cameraView.Options = new BarcodeReaderOptions {   
  Formats = BarcodeFormats.QrCode // or BarcodeFormats.All 
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2.Use TryHarder = true for difficult lighting conditions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🧠 Final Thoughts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That’s it! You’ve now integrated a &lt;strong&gt;fully functional QR Code Scanner in .NET MAUI using ZXing.Net.MAUI&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;ZXing is &lt;strong&gt;open-source, cross-platform, and easy to set up&lt;/strong&gt;, making it an excellent choice for most use cases. With just a few steps — installing the package, setting up permissions, and adding the XAML and C# logic — your MAUI app can now read QR codes and barcodes in real time.&lt;/p&gt;

&lt;p&gt;Whether you’re building a kiosk, attendance app, or mobile tool, ZXing.Net.MAUI gives you the flexibility and reliability you need.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>programming</category>
      <category>computerscience</category>
      <category>mobile</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>supriya shah</dc:creator>
      <pubDate>Fri, 30 Jan 2026 06:09:14 +0000</pubDate>
      <link>https://forem.com/supriya_shah_1e9c3df6158c/-3pm7</link>
      <guid>https://forem.com/supriya_shah_1e9c3df6158c/-3pm7</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/supriya_shah_1e9c3df6158c" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F3697774%2Fb2737369-ff20-4f52-b0ce-e08756278312.png" alt="supriya_shah_1e9c3df6158c"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/supriya_shah_1e9c3df6158c/master-method-overloading-and-overriding-in-android-kotlin-development-jid" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Master Method Overloading and Overriding in Android (Kotlin) Development&lt;/h2&gt;
      &lt;h3&gt;supriya shah ・ Jan 30&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#android&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#software&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#computerscience&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>android</category>
      <category>programming</category>
      <category>software</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>Master Method Overloading and Overriding in Android (Kotlin) Development</title>
      <dc:creator>supriya shah</dc:creator>
      <pubDate>Fri, 30 Jan 2026 06:08:22 +0000</pubDate>
      <link>https://forem.com/supriya_shah_1e9c3df6158c/master-method-overloading-and-overriding-in-android-kotlin-development-jid</link>
      <guid>https://forem.com/supriya_shah_1e9c3df6158c/master-method-overloading-and-overriding-in-android-kotlin-development-jid</guid>
      <description>&lt;p&gt;&lt;strong&gt;Originally published on Medium:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://medium.com/@supsabhi/master-method-overloading-and-overriding-in-android-kotlin-development-46a8f2da6d07" rel="noopener noreferrer"&gt;https://medium.com/@supsabhi/master-method-overloading-and-overriding-in-android-kotlin-development-46a8f2da6d07&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Method overloading and method overriding are very common and core techniques in OOPS programming. When you build apps, you must have come across these terms. They sound similar, but they do completely different jobs! They let you reuse and extend code in smart ways by allowing you to write clean, reusable, and flexible code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overloading&lt;/strong&gt; = same name, different parameters.&lt;br&gt;
&lt;strong&gt;Overriding&lt;/strong&gt; = subclass replaces/extends behavior of a parent class method.&lt;/p&gt;

&lt;p&gt;Let’s look more deeply into each one of these.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Method Overloading&lt;/strong&gt;&lt;br&gt;
Method overloading happens when multiple methods share the same name but have different parameter lists. What it means is there are multiple functions with the same name but different signatures. These differences can be in the number, type, or order of parameters. This different signature allows the compiler to pick the correct function when you call it.&lt;/p&gt;

&lt;p&gt;So, you can say that the main goal of overloading is to make your code more readable and flexible.&lt;/p&gt;

&lt;p&gt;A few important things need to be considered in Kotlin are:&lt;/p&gt;

&lt;p&gt;The compiler resolves which function to call at compile time (this is called Compile-Time Polymorphism) because it knows the parameter types beforehand.&lt;br&gt;
It doesn’t require inheritance. Overloading can happen entirely within one class.&lt;br&gt;
Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
class Calculator {
    fun sum(a: Int, b: Int): Int {
        return a + b
    }
fun sum(a: Int, b: Int, c: Int): Int {
        return a + b + c
    }
    fun sum(a: Double, b: Double): Double {
        return a + b
    }
}
fun main() {
    val calc = Calculator()
    println(calc.sum(2, 3))        // uses (Int, Int)
    println(calc.sum(2, 3, 4))     // uses (Int, Int, Int)
    println(calc.sum(2.5, 3.5))    // uses (Double, Double)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, all the methods have the same name sum, but they differ either in their parameter number or in parameter type.&lt;/p&gt;

&lt;p&gt;In Kotlin, you might see overloading in functions like Toast.makeText()as below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Toast.makeText(Context context, CharSequence text, int duration)
Toast.makeText(Context context, int resId, int duration)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Overloading with extension functions or top-level functions also works — Kotlin treats overloads in that scope too.&lt;br&gt;
You need to be careful with ambiguous overloads: if two overloads are too similar and the compiler cannot clearly pick one, you’ll get an “overload resolution ambiguity” error.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When &amp;amp; why to use overloading&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you have a method that logically does the same thing but you want to support different kinds of inputs (e.g., load(image: String), load(image: Uri), load(image: File)).&lt;br&gt;
When you want to improve readability: you don’t need many method names like loadStringImage, loadUriImage; you just overload load().&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Method Overriding&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Overriding is about inheritance. You have a base (parent) class that defines a method (or abstract method), and a subclass (child class) provides its own implementation of that method (same signature) so that when you call it on the subclass instance, the subclass version runs. This supports runtime polymorphism. You’re essentially taking the parent’s generic instruction and giving it a specific, custom implementation in the child.&lt;/p&gt;

&lt;p&gt;As Android development is built on inheritance, you constantly override functions that the Android system (the parent) defines.&lt;br&gt;
When you create an Android Activity, you inherit the onCreate() method from a parent class like AppCompatActivity.&lt;br&gt;
The parent has a default onCreate() that handles basic setup. You override it to add your specific code.&lt;/p&gt;

&lt;p&gt;Also in Kotlin:&lt;/p&gt;

&lt;p&gt;Classes and methods are final by default (i.e., cannot be inherited/overridden) unless you mark them with open.&lt;br&gt;
In the subclass, you must use the override keyword to indicate you are overriding.&lt;br&gt;
You can call the parent version via super.methodName() if needed.&lt;br&gt;
For example, all lifecycle methods like onCreate(), onStart(), onPause() are open in the Activity class, so you can override them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MainActivity : AppCompatActivity() {
    override fun onPause() {
        super.onPause() // calls the original method from AppCompatActivity
        // your custom logic here
        Log.d("MainActivity", "App is paused")
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here:&lt;br&gt;
override → tells Kotlin we’re redefining a method from the parent.&lt;br&gt;
super.onPause() → calls the original version in the parent class (AppCompatActivity), to keep the Android lifecycle working properly.&lt;br&gt;
Then, we can add our own logic below or above that call.&lt;/p&gt;

&lt;p&gt;So we can say that when overriding an Android lifecycle method (like onCreate), you often call super.onCreate(...) inside your overridden function.&lt;br&gt;
This is you saying, “Do the Parent’s basic setup first, and then run my special code.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why to use overriding&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To customize or extend behavior of a base class method in a subclass.&lt;/li&gt;
&lt;li&gt;To implement interfaces or abstract classes: you provide concrete implementations in subclasses.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Quick Summary: The Difference That Matters&lt;/strong&gt;&lt;br&gt;
Think of it this way:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overloading&lt;/strong&gt; is about &lt;strong&gt;variety&lt;/strong&gt; (one name, many parameter options). It happens horizontally within one class. It lets you create multiple versions of the same method with different inputs.&lt;br&gt;
&lt;strong&gt;Overriding&lt;/strong&gt; is about &lt;strong&gt;specialization&lt;/strong&gt; (one name, one parameter set, one new action). It happens vertically down the inheritance chain. It lets you modify how inherited methods behave.&lt;br&gt;
Mastering these two concepts is key to writing clean, logical, and truly Object-Oriented Kotlin code in your Android applications!&lt;/p&gt;

</description>
      <category>android</category>
      <category>programming</category>
      <category>software</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>MVVM vs Clean Architecture: Key Differences and How They Work Together in Android</title>
      <dc:creator>supriya shah</dc:creator>
      <pubDate>Thu, 22 Jan 2026 08:55:12 +0000</pubDate>
      <link>https://forem.com/supriya_shah_1e9c3df6158c/mvvm-vs-clean-architecture-key-differences-and-how-they-work-together-in-android-5fi4</link>
      <guid>https://forem.com/supriya_shah_1e9c3df6158c/mvvm-vs-clean-architecture-key-differences-and-how-they-work-together-in-android-5fi4</guid>
      <description>&lt;p&gt;Originally published on Medium:&lt;br&gt;
&lt;a href="https://medium.com/@supsabhi/mvvm-vs-clean-architecture-1ecaba107209" rel="noopener noreferrer"&gt;https://medium.com/@supsabhi/mvvm-vs-clean-architecture-1ecaba107209&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imagine you’re building a &lt;strong&gt;house&lt;/strong&gt;.Before you even pick colors or furniture, you need a &lt;strong&gt;blueprint&lt;/strong&gt; of the building — that’s your &lt;strong&gt;architecture&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Then, inside the house, you decide how specific rooms work — that’s your design pattern.&lt;/p&gt;

&lt;p&gt;In Android development, the story is &lt;strong&gt;exactly the same.&lt;/strong&gt;&lt;br&gt;
👉 &lt;strong&gt;Clean Architecture&lt;/strong&gt; is the blueprint for the entire building.&lt;br&gt;
👉 &lt;strong&gt;MVVM&lt;/strong&gt; is the design pattern you choose for your living room and kitchen area.&lt;/p&gt;

&lt;p&gt;They don’t compete — they &lt;strong&gt;work together&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;🧩 &lt;strong&gt;Architecture vs Design Pattern&lt;/strong&gt;&lt;br&gt;
We can say that architecture is nothing but a big picture that tells us about the overall structure of a building (or an app).&lt;/p&gt;

&lt;p&gt;In software development, it’s like putting your most valuable asset — your &lt;strong&gt;core business logic&lt;/strong&gt; — in a &lt;strong&gt;protected vault&lt;/strong&gt; at the center of your app.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;design pattern&lt;/strong&gt;, on the other hand, is a &lt;strong&gt;small, proven solution&lt;/strong&gt; to a recurring problem inside that architecture.&lt;/p&gt;

&lt;p&gt;🧱 &lt;strong&gt;Clean Architecture — The Blueprint&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Clean Architecture&lt;/strong&gt; focuses on &lt;strong&gt;maintainability&lt;/strong&gt; and &lt;strong&gt;scalability&lt;/strong&gt;.&lt;br&gt;
It follows one golden rule:&lt;/p&gt;

&lt;p&gt;🧭 &lt;em&gt;The inner circle never knows anything about the outer circle.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What does that mean?&lt;br&gt;
The &lt;strong&gt;core logic&lt;/strong&gt; doesn’t care if you’re showing data on a phone, tablet, or smart TV.&lt;br&gt;
The core logic doesn’t care if data comes from Room, a remote API, or a simple text file.&lt;br&gt;
So, even if your UI or database changes, your core business logic remains untouched.&lt;br&gt;
This is achieved through the** Dependency Inversion Principle (DIP)** — outer layers must implement the &lt;strong&gt;interfaces&lt;/strong&gt; defined by the inner layers. It’s like flipping dependencies upside down so your core never depends on external tools.&lt;/p&gt;

&lt;p&gt;🧠 &lt;strong&gt;The Domain Layer (The Brain / The Core)&lt;/strong&gt;&lt;br&gt;
What it is: The innermost layer holding your core business rules.&lt;br&gt;
Key Components: Entities: Pure data models like Userand Use Cases: Actions like LoginUserUseCase.&lt;/p&gt;

&lt;p&gt;💾 &lt;strong&gt;The Data Layer (The Storage / The Muscles)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it is&lt;/strong&gt;: Handles fetching, storing, and managing data from external systems.&lt;br&gt;
&lt;strong&gt;Key Components&lt;/strong&gt;:Repositories: Decide where to fetch data from — network or local database.Data Sources: Retrofit for network calls, Room for local storage.Connection: Implements the interfaces defined in the Domain Layer.&lt;/p&gt;

&lt;p&gt;📱 &lt;strong&gt;The Presentation Layer (The Face / The Output)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it is&lt;/strong&gt;: Responsible for showing data and capturing user actions.&lt;br&gt;
&lt;strong&gt;Key Components&lt;/strong&gt;: Activities, Fragments, Composables (Views), and ViewModels.&lt;br&gt;
The Role: Talks to the Domain Layer (via Use Cases) to get data and uses a pattern like MVVM to manage the UI state.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;In summary:&lt;/strong&gt;&lt;br&gt;
Clean Architecture is &lt;strong&gt;highly maintainable, easy to test&lt;/strong&gt;, and &lt;strong&gt;independent of frameworks&lt;/strong&gt; — though it can feel complex initially and needs a bit more setup.&lt;/p&gt;

&lt;p&gt;🎯 &lt;strong&gt;MVVM Pattern — The UI Hero&lt;/strong&gt;&lt;br&gt;
MVVM (Model–View–ViewModel) focuses on keeping the Presentation Layer clean and reactive.&lt;br&gt;
Its main goal? Make the View as “dumb” as possible.&lt;/p&gt;

&lt;p&gt;🔹 &lt;strong&gt;View (Activity / Fragment / Composable)&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Role&lt;/strong&gt;: The screen. Draws UI elements and handles user input (clicks, swipes, typing).&lt;br&gt;
&lt;strong&gt;Key Action&lt;/strong&gt;: Observes the ViewModel for data changes and sends user actions back to it.&lt;/p&gt;

&lt;p&gt;🔹 &lt;strong&gt;ViewModel (The Screen’s Brain)&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Role&lt;/strong&gt;: Holds UI state — what to display, whether to show a loading spinner, etc.&lt;br&gt;
Survives configuration changes (like screen rotation).&lt;br&gt;
Acts like a middle manager between View and Model.&lt;br&gt;
&lt;strong&gt;Key Action&lt;/strong&gt;:&lt;br&gt;
Doesn’t reference Android Views directly.&lt;br&gt;
Talks to Use Cases from the Domain Layer.&lt;br&gt;
Updates observable data (LiveData, StateFlow).&lt;/p&gt;

&lt;p&gt;🔹 &lt;strong&gt;Model (The Data Source)&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Role&lt;/strong&gt;: Represents your actual data — users, products, etc.&lt;br&gt;
&lt;strong&gt;Key Action&lt;/strong&gt;: Usually maps to your Domain/Data Layers.&lt;br&gt;
The ViewModel doesn’t handle data logic itself — it delegates to a Use Case.&lt;/p&gt;

&lt;p&gt;⚙️ &lt;strong&gt;How MVVM Works&lt;/strong&gt;&lt;br&gt;
User clicks a button → ViewModel reacts → Fetches data from Model → Updates UI automatically&lt;/p&gt;

&lt;p&gt;The View simply &lt;strong&gt;watches&lt;/strong&gt; the ViewModel’s data and updates itself.&lt;br&gt;
That makes debugging easy — you always know &lt;strong&gt;where your data came from&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;However, if too much logic creeps into the ViewModel, it can become messy.&lt;/p&gt;

&lt;p&gt;🏁 &lt;strong&gt;Clean Architecture + MVVM = Perfect Combo&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can now say that:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Clean Architecture&lt;/strong&gt; = Macro-level strategy (big picture)&lt;br&gt;
&lt;strong&gt;MVVM&lt;/strong&gt; = Micro-level pattern (how UI works)&lt;/p&gt;

&lt;p&gt;MVVM can live &lt;strong&gt;inside&lt;/strong&gt; Clean Architecture as the bridge between the &lt;strong&gt;UI layer&lt;/strong&gt; and the &lt;strong&gt;business logic layer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You can use MVVM without Clean Architecture, but your code will be &lt;strong&gt;less scalable&lt;/strong&gt; and &lt;strong&gt;harder to test&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Clean Architecture&lt;/strong&gt; provides the &lt;strong&gt;Domain&lt;/strong&gt; and &lt;strong&gt;Data layers&lt;/strong&gt; (the app’s brain and muscles).&lt;br&gt;
&lt;strong&gt;MVVM&lt;/strong&gt; provides the &lt;strong&gt;Presentation Layer&lt;/strong&gt; (the face) — making the final UI clean, efficient, and testable.&lt;/p&gt;

&lt;p&gt;🧭 &lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;🏗️ &lt;strong&gt;Clean Architecture&lt;/strong&gt; = The entire building plan.&lt;br&gt;
🎨 &lt;strong&gt;MVVM&lt;/strong&gt; = The design pattern for your rooms.&lt;br&gt;
💡 &lt;strong&gt;Together&lt;/strong&gt; = A solid, flexible, and testable Android app.&lt;br&gt;
Start small:&lt;br&gt;
Apply MVVM first, then gradually refactor your project toward Clean Architecture as it grows.&lt;br&gt;
That’s how you move from “it works” to “it scales beautifully.” 🚀&lt;/p&gt;

</description>
      <category>android</category>
      <category>mobile</category>
      <category>architecture</category>
      <category>designpatterns</category>
    </item>
    <item>
      <title>Sockets in Android: From WebSockets to Socket.IO (with Jetpack Compose Example)</title>
      <dc:creator>supriya shah</dc:creator>
      <pubDate>Mon, 19 Jan 2026 07:06:27 +0000</pubDate>
      <link>https://forem.com/supriya_shah_1e9c3df6158c/sockets-in-android-from-websockets-to-socketio-with-jetpack-compose-example-3j7j</link>
      <guid>https://forem.com/supriya_shah_1e9c3df6158c/sockets-in-android-from-websockets-to-socketio-with-jetpack-compose-example-3j7j</guid>
      <description>&lt;p&gt;Originally published on Medium:&lt;br&gt;
&lt;a href="https://medium.com/@supsabhi/sockets-in-android-from-websockets-to-socket-io-with-jetpack-compose-example-5773828ba05b" rel="noopener noreferrer"&gt;https://medium.com/@supsabhi/sockets-in-android-from-websockets-to-socket-io-with-jetpack-compose-example-5773828ba05b&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Real-time updates are a real challenge! Every time we play games or use a chat application, the instant updates on screen always amaze us. How does the app receive updates without constantly refreshing APIs?&lt;br&gt;
The answer is “Sockets.” Let’s dive deeper into sockets, explore different types, focus on IO sockets, and see how to implement them in Android Jetpack Compose.&lt;/p&gt;

&lt;p&gt;A socket is like a live communication channel between your Android app and a server. Unlike standard HTTP APIs where you request data and wait for a reply, sockets remain connected and enable two-way communication. Think of it as a direct digital pipe — data can flow both ways, supporting fast, two-way updates without repetitive polling.&lt;/p&gt;

&lt;p&gt;In practice, you can distinguish between HTTP and sockets like this:&lt;br&gt;
HTTP: You send a request, the server replies, communication happens, and the process ends.&lt;br&gt;
Sockets: Sockets can be viewed as ,suppose in the process of opening a phone call, you pick up phone and “keep the call alive” and both sides can talk anytime&lt;/p&gt;

&lt;p&gt;There are different types of sockets, each used for specific purposes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WebSockets&lt;/strong&gt;: WebSocket is a W3C and IETF standardized protocol that offers a persistent channel over a single TCP connection. You can send or receive as much data as needed, without reopening new HTTP requests. It’s lightweight, efficient, and ideal for streaming data. WebSockets are commonly used in live sports updates, stock prices, collaborative docs, and IoT device status — where low latency and immediate updates are essential.&lt;br&gt;
&lt;strong&gt;Socket.IO&lt;/strong&gt;: Socket.IO isn’t a protocol, but a full-featured library built on top of WebSockets (with fallbacks). It manages fallbacks, reconnections, broadcasting, event naming, and more. It’s easier for developers because it solves real-world connection issues out of the box. Socket.IO is mainly used for chat apps, live games, and push notification dashboards.&lt;br&gt;
&lt;strong&gt;Raw TCP/UDP Sockets&lt;/strong&gt;: These are low-level protocols. TCP enables reliable raw byte transfer and is used in file transfer and messaging. UDP is faster but less reliable than TCP and is used in video streaming and gaming. Raw TCP/UDP sockets offer custom device-to-device control and binary protocol capabilities.&lt;br&gt;
Let’s focus more on our star: Socket.IO.&lt;/p&gt;

&lt;p&gt;Socket.IO smooths over many networking headaches, especially for mobile: reconnection logic, event-centric APIs, message buffering during downtimes, and support for various network topologies. It certainly deserves special recognition.&lt;/p&gt;

&lt;p&gt;Implementation in Android Jetpack Compose&lt;br&gt;
Below is an example of live updating a dashboard based on the server’s latest information.&lt;br&gt;
(First, add implementation&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'io.socket:socket.io-client:2.1.0' 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to your build.gradle.)&lt;/p&gt;

&lt;p&gt;Make sure the socket client version matches the server version.&lt;br&gt;
Also, add the internet usage permission in your manifest.&lt;/p&gt;

&lt;p&gt;Data Model Class&lt;/p&gt;

&lt;p&gt;data class DashBoardMessage(val var1: String, val var2: String, val var3: String)&lt;br&gt;
ViewModel&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class DashBoardViewModel : ViewModel() {
    var latestMessage by mutableStateOf&amp;lt;DashBoardMessage?&amp;gt;(null)
        private set

    private val socketManager = SocketManager()

    fun start() {
        socketManager.connect { message -&amp;gt;
            latestMessage = message
        }
    }

    override fun onCleared() {
        super.onCleared()
        socketManager.disconnect()
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Socket Manager&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class SocketManager {
    private var socket: Socket? = null

    fun connect(onMessage: (DashBoardMessage) -&amp;gt; Unit) {
        try {
            val opts = IO.Options().apply { forceNew = true }
            socket = IO.socket("https://your-socket-server.com", opts)

            socket?.on(Socket.EVENT_CONNECT) {
                Log.d("SocketIO", "Connected")
            }

            socket?.on("message") { args -&amp;gt;
                if (args.isNotEmpty() &amp;amp;&amp;amp; args[0] is JSONObject) {
                    val json = args[0] as JSONObject
                    val msg = DashBoardMessage(
                        var1 = json.optString("var1"),
                        var2 = json.optString("var2"),
                        var3 = json.optString("var3")
                    )
                    Handler(Looper.getMainLooper()).post {
                        onMessage(msg)
                    }
                }
            }

            socket?.connect()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    fun disconnect() {
        socket?.disconnect()
        socket?.off()
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compose Screen&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
@Composable
fun DashboardScreen(viewModel: DashBoardViewModel = viewModel()) {
    val msg = viewModel.latestMessage

    LaunchedEffect(Unit) {
        viewModel.start()
    }

    Column(modifier = Modifier.padding(16.dp)) {
        Text("Var1: ${msg?.var1 ?: ""}")
        Text("Var2: ${msg?.var2 ?: ""}")
        Text("Var3: ${msg?.var3 ?: ""}")
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this setup, you get real-time, event-driven updates in a Compose UI. Incoming messages instantly update the screen, and sending a message emits it to the server — no need for manual thread handling or traditional callbacks.&lt;/p&gt;

&lt;p&gt;Sockets might sound technical, but with tools like Socket.IO, creating a real-time, mobile-friendly Android app becomes straightforward.&lt;/p&gt;

&lt;p&gt;So next time you need live updates — whether for a parking system, chat app, or stock ticker — reach for sockets instead of hammering your APIs.&lt;br&gt;
GitHub Repository for Hands-On Reference&lt;/p&gt;

&lt;p&gt;To make this article more practical and hands-on, I’ve published a public GitHub repository that demonstrates everything discussed above.&lt;/p&gt;

&lt;p&gt;📂 &lt;strong&gt;GitHub Repository&lt;/strong&gt;:&lt;br&gt;
&lt;a href="https://github.com/supsabhi/IoSocketJetPack.git" rel="noopener noreferrer"&gt;https://github.com/supsabhi/IoSocketJetPack.git&lt;/a&gt;&lt;/p&gt;

</description>
      <category>android</category>
      <category>mobile</category>
      <category>kotlin</category>
      <category>programming</category>
    </item>
    <item>
      <title>LazyColumn vs RecyclerView: A Developer’s Guide to Modern Android Lists</title>
      <dc:creator>supriya shah</dc:creator>
      <pubDate>Fri, 16 Jan 2026 09:28:33 +0000</pubDate>
      <link>https://forem.com/supriya_shah_1e9c3df6158c/lazycolumn-vs-recyclerview-a-developers-guide-to-modern-android-lists-50gf</link>
      <guid>https://forem.com/supriya_shah_1e9c3df6158c/lazycolumn-vs-recyclerview-a-developers-guide-to-modern-android-lists-50gf</guid>
      <description>&lt;p&gt;Originally published on Medium:&lt;br&gt;
&lt;a href="https://medium.com/@supsabhi/lazycolumn-vs-recyclerview-a-developers-guide-to-modern-android-lists-aecae66c3356" rel="noopener noreferrer"&gt;https://medium.com/@supsabhi/lazycolumn-vs-recyclerview-a-developers-guide-to-modern-android-lists-aecae66c3356&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Making the right choice for your Android app’s &lt;strong&gt;scrollable content&lt;/strong&gt;&lt;br&gt;
Just imagine, you’re building an Android app that needs to display a list of items — maybe it’s a social media feed, a shopping cart, or a contact list. Practically, there will be very few apps which will not have any kind of list. While developing an app when a developer needs to choose between the tried-and-true RecyclerView or embrace Jetpack Compose’s &lt;strong&gt;LazyColumn&lt;/strong&gt;, the real struggle starts.&lt;/p&gt;

&lt;p&gt;This decision isn’t just about following the latest trends. It’s about choosing the right tool that will make your code cleaner, your app more performant, and your development experience smoother.&lt;/p&gt;

&lt;p&gt;For years, RecyclerView was the standard. With Jetpack Compose, LazyColumn brings a new, more human-friendly approach. But what really sets them apart?&lt;/p&gt;

&lt;p&gt;Let’s dive deep into both approaches and help you make an informed decision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Traditional Tried RecyclerView&lt;/strong&gt;&lt;br&gt;
RecyclerView has been the backbone of Android list displays since 2014. It replaced ListView with a more flexible and efficient design, introducing the ViewHolder pattern and giving developers granular control over how items are displayed and recycled.&lt;/p&gt;

&lt;p&gt;Basically, RecyclerView is nothing but a robust, flexible way of showing long lists or grids of views. It acts as a sophisticated recycling system. Instead of creating a new view for every item in your list (which would be memory-intensive), it creates just enough views to fill the screen plus a few extras, saving both memory and processor work. As you scroll, views that disappear from the top are recycled and reused for new items appearing at the bottom.&lt;/p&gt;

&lt;p&gt;But as they say, “everything comes with a price.” RecyclerView too has its own challenges; we will look into it in detail. First, let’s see how one can set up RecyclerView in an application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Data class
data class Task(val id: Int, val title: String, val isCompleted: Boolean)
// ViewHolder
class TaskViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    private val titleText: TextView = itemView.findViewById(R.id.task_title)
    private val checkbox: CheckBox = itemView.findViewById(R.id.task_checkbox)

    fun bind(task: Task, onTaskToggle: (Task) -&amp;gt; Unit) {
        titleText.text = task.title
        checkbox.isChecked = task.isCompleted
        checkbox.setOnCheckedChangeListener { _, isChecked -&amp;gt;
            onTaskToggle(task.copy(isCompleted = isChecked))
        }
    }
}
// Adapter
class TaskAdapter(
    private var tasks: List&amp;lt;Task&amp;gt;,
    private val onTaskToggle: (Task) -&amp;gt; Unit
) : RecyclerView.Adapter&amp;lt;TaskViewHolder&amp;gt;() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TaskViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.item_task, parent, false)
        return TaskViewHolder(view)
    }

    override fun onBindViewHolder(holder: TaskViewHolder, position: Int) {
        holder.bind(tasks[position], onTaskToggle)
    }

    override fun getItemCount() = tasks.size

    fun updateTasks(newTasks: List&amp;lt;Task&amp;gt;) {
        tasks = newTasks
        notifyDataSetChanged()
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So basically, how RecyclerView is set up is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adapter&lt;/strong&gt;: Custom code links your data to the list items&lt;br&gt;
&lt;strong&gt;ViewHolder&lt;/strong&gt;: Custom classes track references for each view in an item for fast updates&lt;br&gt;
&lt;strong&gt;LayoutManager&lt;/strong&gt;: Controls if your list is vertical, horizontal, or grid&lt;br&gt;
&lt;strong&gt;XML layouts&lt;/strong&gt;: Most code is separate from display — declarative UI felt far away here&lt;br&gt;
Now let’s review deeper about RecyclerView’s strengths and its challenges.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RecyclerView’s Strengths&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;1. Battle-Tested Performance&lt;/strong&gt; RecyclerView has been optimized over nearly a decade. It handles large datasets efficiently and provides smooth scrolling even on older devices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Extensive Customization&lt;/strong&gt; Want custom animations? Multiple view types? Complex layouts? RecyclerView gives you the tools to build almost anything. The ItemDecorator system lets you add dividers, spacing, and custom decorations with precision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RecyclerView’s Challenges&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;1. Boilerplate Overload&lt;/strong&gt; Look at that code above. For a simple list, you need a ViewHolder, an Adapter, layout files, and proper setup. That’s a lot of ceremony for displaying a list.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. XML Layout Dependencies&lt;/strong&gt; You’re still tied to XML layouts, which means context switching between Kotlin and XML files. Design-time previews can be limited.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Manual State Management&lt;/strong&gt; Updating lists requires careful state management. Forget to call notifyItemChanged() and your UI won't update. Call notifyDataSetChanged() too often and performance suffers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let’s Check Out the New Player in the Market: LazyColumn&lt;/strong&gt;&lt;br&gt;
LazyColumn arrived with Jetpack Compose, representing a fundamental shift in how we build Android UIs. Instead of the imperative “how” of RecyclerView, LazyColumn focuses on the declarative “what.”&lt;/p&gt;

&lt;p&gt;LazyColumn is the Compose-native component for vertically scrolling lists. The best part: there’s no Adapter, no XML, just Kotlin in a “what, not how” style.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Composable
fun TaskList(
    tasks: List&amp;lt;Task&amp;gt;,
    onTaskToggle: (Task) -&amp;gt; Unit,
    modifier: Modifier = Modifier
) {
    LazyColumn(
        modifier = modifier.fillMaxSize(),
        verticalArrangement = Arrangement.spacedBy(8.dp),
        contentPadding = PaddingValues(16.dp)
    ) {
        items(tasks) { task -&amp;gt;
            TaskItem(
                task = task,
                onToggle = { onTaskToggle(it) }
            )
        }
    }
}
@Composable
fun TaskItem(
    task: Task,
    onToggle: (Task) -&amp;gt; Unit,
    modifier: Modifier = Modifier
) {
    Card(
        modifier = modifier.fillMaxWidth(),
        elevation = CardDefaults.cardElevation(defaultElevation = 2.dp)
    ) {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(16.dp),
            horizontalArrangement = Arrangement.SpaceBetween,
            verticalAlignment = Alignment.CenterVertically
        ) {
            Text(
                text = task.title,
                style = MaterialTheme.typography.bodyLarge,
                modifier = Modifier.weight(1f)
            )
            Checkbox(
                checked = task.isCompleted,
                onCheckedChange = { onToggle(task.copy(isCompleted = it)) }
            )
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;}&lt;br&gt;
Now here, if you notice carefully, you will see that there are no adapters, no view holders, no layout inflation. Just describe what you want.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LazyColumn’s Strengths:&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;1. Simplicity and Code Readability&lt;/strong&gt; LazyColumn provides a simple way to develop, increasing code readability. You can see the entire list structure at a glance without jumping between multiple files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Automatic State Management&lt;/strong&gt; When your state changes, Compose automatically recomposes only the affected items. No need to manually manage notify calls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Built-in Modern Features&lt;/strong&gt; Spacing, padding, and arrangements are built-in. Need sticky headers? Just use stickyHeader {}. Want different item types? Use multiple items {} blocks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Type Safety Everything&lt;/strong&gt; is strongly typed. No more casting views or dealing with position-based lookups that might fail at runtime.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance Comparison&lt;/strong&gt;&lt;br&gt;
In case of memory usage, both LazyColumn and RecyclerView use similar lazy loading strategies. They only create and maintain views/composables for visible items plus a small buffer.&lt;/p&gt;

&lt;p&gt;If we want to compare scrolling performance, then RecyclerView has a slight edge in raw scrolling performance due to its mature optimizations and lower-level control. However, LazyColumn’s performance is excellent and continues to improve with each Compose release.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Verdict&lt;/strong&gt;&lt;br&gt;
The verdict can be sorted down as:&lt;/p&gt;

&lt;p&gt;Both RecyclerView and LazyColumn are excellent tools for different contexts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LazyColumn is the future&lt;/strong&gt; for new projects, teams embracing modern Android development, and applications prioritizing development velocity and maintainability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RecyclerView remains the right choice&lt;/strong&gt; for projects with established View-based architectures, teams with deep RecyclerView expertise, or applications with extremely demanding performance requirements.&lt;/p&gt;

&lt;p&gt;For lists with frequent state changes or dynamic data: LazyColumn’s model makes these scenarios less error-prone, and animations come much easier.&lt;/p&gt;

&lt;p&gt;The key is making an informed decision based on your specific context rather than following trends blindly. Both tools can help you build great Android apps — choose the one that fits your project best.&lt;/p&gt;

&lt;p&gt;What’s your experience with LazyColumn vs RecyclerView? Have you made the switch, or are you still evaluating? Share your thoughts and challenges in the comments below.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>android</category>
      <category>mobile</category>
      <category>ui</category>
    </item>
    <item>
      <title>Unlocking NFC: Reading MIFARE Cards with Jetpack Compose</title>
      <dc:creator>supriya shah</dc:creator>
      <pubDate>Wed, 14 Jan 2026 12:01:14 +0000</pubDate>
      <link>https://forem.com/supriya_shah_1e9c3df6158c/unlocking-nfc-reading-mifare-cards-with-jetpack-compose-4jib</link>
      <guid>https://forem.com/supriya_shah_1e9c3df6158c/unlocking-nfc-reading-mifare-cards-with-jetpack-compose-4jib</guid>
      <description>&lt;p&gt;Originally published on Medium:&lt;br&gt;
&lt;a href="https://medium.com/@supsabhi/unlocking-nfc-reading-mifare-cards-with-jetpack-compose-bf250171d1f1" rel="noopener noreferrer"&gt;https://medium.com/@supsabhi/unlocking-nfc-reading-mifare-cards-with-jetpack-compose-bf250171d1f1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NFC (Near Field Communication)&lt;/strong&gt; is one of those technologies we use almost daily — without even realising it. From tapping your phone at the supermarket checkout to scanning an access badge at work, NFC has quietly become a part of our everyday lives.&lt;/p&gt;

&lt;p&gt;If you’re building an Android app that involves card reading — for public transportation, access control, loyalty programs, or event tickets — understanding how to implement NFC tag reading is essential. In this post, we’ll explore how to read &lt;strong&gt;MIFARE Classic&lt;/strong&gt; tags using Android and Jetpack Compose.&lt;/p&gt;

&lt;p&gt;Before diving into the implementation, let’s briefly talk about the types of NFC tags you may encounter. NFC Forum classifies tags into Type 1 to Type 5, and among the most popular families are:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MIFARE Classic&lt;/strong&gt; — Found in transport cards, hotel keys, and loyalty cards. Widely used, but not the most secure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MIFARE Ultralight&lt;/strong&gt; — Low-cost and used for disposable tickets or event passes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MIFARE DESFire&lt;/strong&gt; — Designed for higher-security applications, but more expensive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NTAG Series&lt;/strong&gt; — Known for better security and compatibility. A solid choice for general-purpose usage.&lt;/p&gt;

&lt;p&gt;Each has its pros and cons.Selection of card depends on your app’s needs — security, cost, and data volume.&lt;/p&gt;

&lt;p&gt;Let’s build a basic app that can read MIFARE Classic tags. We’ll use Jetpack Compose for UI and handle NFC in a standard way.&lt;/p&gt;

&lt;p&gt;Step 1: Add Required Permissions and Features&lt;br&gt;
In your AndroidManifest.xml, declare NFC permissions and features:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;uses-permission android:name="android.permission.NFC" /&amp;gt;
&amp;lt;uses-feature android:name="android.hardware.nfc" android:required="true" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, add an intent-filter and meta-data block to capture the tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;intent-filter&amp;gt;
    &amp;lt;action android:name="android.nfc.action.TECH_DISCOVERED" /&amp;gt;
&amp;lt;/intent-filter&amp;gt;
&amp;lt;meta-data
    android:name="android.nfc.action.TECH_DISCOVERED"
    android:resource="@xml/nfc_tech_filter" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And create a res/xml/nfc_tech_filter.xml file with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"&amp;gt;
    &amp;lt;tech-list&amp;gt;
        &amp;lt;tech&amp;gt;android.nfc.tech.MifareClassic&amp;lt;/tech&amp;gt;
    &amp;lt;/tech-list&amp;gt;
&amp;lt;/resources&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Capture the Tag in MainActivity&lt;br&gt;
Set up the NFC adapter and foreground dispatch in your MainActivity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MainActivity : ComponentActivity() {
    private var nfcAdapter: NfcAdapter? = null
    private val viewModel: NfcViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        nfcAdapter = NfcAdapter.getDefaultAdapter(this)
        setContent {
            NfcScreen(viewModel)
        }
    }
override fun onResume() {
        super.onResume()
        val intent = Intent(this, javaClass).apply {
            addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
        }
        val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE)
        nfcAdapter?.enableForegroundDispatch(this, pendingIntent, null, null)
    }
    override fun onPause() {
        super.onPause()
        nfcAdapter?.disableForegroundDispatch(this)
    }
    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        val tag = intent.getParcelableExtra&amp;lt;Tag&amp;gt;(NfcAdapter.EXTRA_TAG)
        tag?.let {
            val result = readMifareClassic(it)
            viewModel.updateNfcData(result)
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 3: Read MIFARE Classic Data&lt;br&gt;
This function reads data from each block of a MIFARE Classic tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fun readMifareClassic(tag: Tag): String {
    val mfc = MifareClassic.get(tag) ?: return "Not a MIFARE Classic tag"
    val sb = StringBuilder()
try {
        mfc.connect()
        val sectorCount = mfc.sectorCount
        for (sector in 0 until sectorCount) {
            val auth = mfc.authenticateSectorWithKeyA(sector, MifareClassic.KEY_DEFAULT)
            if (auth) {
                val blockCount = mfc.getBlockCountInSector(sector)
                val blockIndex = mfc.sectorToBlock(sector)
                for (block in 0 until blockCount) {
                    val data = mfc.readBlock(blockIndex + block)
                    sb.append("Sector $sector Block $block: ${data.joinToString(" ") { "%02X".format(it) }}\n")
                }
            } else {
                sb.append("Sector $sector: Authentication failed\n")
            }
        }
    } catch (e: IOException) {
        sb.append("Error: ${e.localizedMessage}")
    } finally {
        try { mfc.close() } catch (_: IOException) {}
    }
    return sb.toString()
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 4: Store and Display the Data Using ViewModel + Compose&lt;br&gt;
We’ll use a ViewModel to hold the NFC data and update the UI reactively.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class NfcViewModel : ViewModel() {
    var nfcData by mutableStateOf("Scan a MIFARE Classic tag")
        private set
fun updateNfcData(data: String) {
        nfcData = data
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Jetpack Compose UI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Composable
fun NfcScreen(viewModel: NfcViewModel) {
    val nfcData = viewModel.nfcData
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(24.dp),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text("Scan MIFARE Tag", fontSize = 24.sp)
        Spacer(modifier = Modifier.height(16.dp))
        Text(text = nfcData, fontSize = 18.sp, color = Color.DarkGray)
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it — you now have a working Android app that can scan and read MIFARE Classic NFC tags using Jetpack Compose!&lt;/p&gt;

&lt;p&gt;This is just the foundation. You can expand this to:Write to NFC tags,Authenticate with custom keys,Handle different tag types (Ultralight, DESFire, NTAG),Encrypt/decrypt data blocks&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;br&gt;
While MIFARE Classic is commonly used, it’s worth noting that it has some known security weaknesses. For sensitive data, consider more secure alternatives like MIFARE DESFire or NTAG cards. Always choose your NFC tech based on the use-case.&lt;/p&gt;

&lt;p&gt;Whether you’re building an access control system or creating an innovative event app, integrating NFC can take your user experience to the next level.&lt;/p&gt;

&lt;p&gt;Let me know in the comments if you’d like a follow-up post on writing to NFC tags ?&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>android</category>
      <category>programming</category>
      <category>nfc</category>
    </item>
    <item>
      <title>Exploring Supabase for Android: A Modern Alternative to Firebase</title>
      <dc:creator>supriya shah</dc:creator>
      <pubDate>Mon, 12 Jan 2026 06:52:02 +0000</pubDate>
      <link>https://forem.com/supriya_shah_1e9c3df6158c/exploring-supabase-for-android-a-modern-alternative-to-firebase-79i</link>
      <guid>https://forem.com/supriya_shah_1e9c3df6158c/exploring-supabase-for-android-a-modern-alternative-to-firebase-79i</guid>
      <description>&lt;p&gt;Originally published on Medium:&lt;br&gt;
&lt;a href="https://medium.com/@supsabhi/exploring-supabase-for-android-a-modern-alternative-to-firebase-f8a61ddb886b" rel="noopener noreferrer"&gt;https://medium.com/@supsabhi/exploring-supabase-for-android-a-modern-alternative-to-firebase-f8a61ddb886b&lt;/a&gt;&lt;br&gt;
For years, Firebase has been the go-to solution for Android developers needing user authentication, simplified backend development, and features like push notifications. It’s been so popular that, for many, it was the only real choice. But now, there’s a new contender in the arena: Supabase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Supabase?&lt;/strong&gt;&lt;br&gt;
Founded in 2020, &lt;strong&gt;Supabase&lt;/strong&gt; is an open-source, serverless platform designed to make backend development easier and more flexible. It serves as a powerful alternative to Firebase, offering a robust set of features that cover everything from authentication to real-time data updates.&lt;/p&gt;

&lt;p&gt;If you’re an Android developer, you’ll appreciate that Supabase is built on top of PostgreSQL, a relational database. This means your data is stored in tables with rows and columns, and you can use full-fledged SQL queries — a big difference from Firebase’s document-based, JSON storage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Features of Supabase&lt;/strong&gt;&lt;br&gt;
Multiple Authentication Options: Supports email/password, social logins, and more.&lt;/p&gt;

&lt;p&gt;Real-Time Updates: Perfect for apps that need live data synchronization.&lt;br&gt;
Push Notifications: Easy to set up and integrate.&lt;br&gt;
Strong Security: Leverages PostgreSQL’s Row-Level Security (RLS) for fine-grained access control.&lt;br&gt;
Easy Setup: Designed for quick onboarding and minimal configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Getting Started with Supabase on Android&lt;/strong&gt;&lt;br&gt;
To use Supabase in your Android project, you’ll need to include the Supabase libraries and a networking client — most commonly, Ktor. If you’re not familiar with Ktor, I’ve written a detailed guide on how to integrate it into your project, which you can find here.&lt;/p&gt;

&lt;p&gt;Adding Dependencies&lt;br&gt;
In your app-level build.gradle, add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
plugins {
    kotlin("plugin.serialization")
}
dependencies {
    // Navigation
    implementation(libs.androidx.navigation.compose)
    // Network Image 
    implementation(libs.coil.compose)
    // Supabase
    implementation(platform(libs.supabase.bom))
    implementation(libs.realtime.kt)
    implementation(libs.postgrest.kt)
    implementation(libs.ktor.client.android)
    implementation(libs.kotlinx.serialization.json)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in your project-level build.gradle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plugins {
    kotlin("jvm") version "2.0.0"
    kotlin("plugin.serialization") version "2.0.0"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Setting Up Your Database&lt;/strong&gt;&lt;br&gt;
Create a Supabase Account:&lt;br&gt;
Go to supabase.com and create a new project.&lt;br&gt;
Create a Table:&lt;br&gt;
For this example, let’s make a simple “vehicle” table with the following columns:&lt;br&gt;
id (Primary key, auto-increment)&lt;/p&gt;

&lt;p&gt;name (Text)&lt;/p&gt;

&lt;p&gt;model (Text)&lt;/p&gt;

&lt;p&gt;year (Integer)&lt;/p&gt;

&lt;p&gt;For simplicity, we’ll skip enabling Row-Level Security (RLS) for now, but we’ll enable real-time updates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating the Data Model&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Back in your Android project, let’s define a data class Vehicle&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data class Vehicle(
    val id: String? = null,
    val name: String,
    val model: String,
    val year: Int,
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Initializing the Supabase Client&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In MainActivity, let’s set up the Supabase client&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            SupaVehicleAppTheme {
                val supabaseClient = createSupabaseClient(
                    supabaseKey = "YOUR_SUPABASE_KEY",
                    supabaseUrl = "YOUR_SUPABASE_URL"
                ) {
                    install(Realtime)
                    install(Postgrest)
                    httpConfig {
                        this.install(WebSockets)
                    }
                }
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll find your project’s API key and URL in the Supabase dashboard under the project API information section.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performing CRUD Operations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here’s how you can interact with your Supabase database from your Android app:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fetch Vehicles:&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;suspend fun getVehicleList() =
    supabase.from("vehicle")
        .select()
        .decodeList&amp;lt;Vehicle&amp;gt;()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Insert a Vehicle:&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;suspend fun insertVehicle(vehicleToAdd: Vehicle) {
    supabase.from("vehicle").insert(vehicleToAdd)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Delete a Vehicle:&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;suspend fun deleteVehicle(vehicleToDelete: Vehicle) {
    supabase.from("vehicle").delete {
        filter {
            Vehicle::id eq vehicleToDelete.id
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Update a Vehicle:&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;suspend fun updateVehicle(vehicleToUpdate: Vehicle) {
    supabase.from("vehicle").update(
        {
            set("name", vehicleToUpdate.name)
        }
    ) {
        filter {
            eq("id", vehicleToUpdate.id)
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Upsert a Vehicle:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Upsert is a handy operation that either inserts a new row or updates an existing one if it already exists.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;suspend fun upsertVehicle(vehicleToUpsert: Vehicle) {
    supabase.from("vehicle").upsert(vehicleToUpsert)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Wrapping Up&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With these basic operations, you can manage your data in Supabase and display it in your app as needed. &lt;strong&gt;Supabase is a flexible, open-source alternative to Firebase&lt;/strong&gt;, especially if you prefer relational databases and full SQL support.From managing real-time data to implementing secure authentication, Supabase offers a modern and developer-friendly backend solution.&lt;/p&gt;

&lt;p&gt;I hope this guide helps you get started with Supabase on Android. If you have any questions or want to dive deeper, feel free to reach out!&lt;/p&gt;

</description>
      <category>android</category>
      <category>mobile</category>
      <category>supabase</category>
      <category>firebase</category>
    </item>
    <item>
      <title>Effortless Android Logging with Timber and Kotlin</title>
      <dc:creator>supriya shah</dc:creator>
      <pubDate>Thu, 08 Jan 2026 08:49:29 +0000</pubDate>
      <link>https://forem.com/supriya_shah_1e9c3df6158c/effortless-android-logging-with-timber-and-kotlin-8h8</link>
      <guid>https://forem.com/supriya_shah_1e9c3df6158c/effortless-android-logging-with-timber-and-kotlin-8h8</guid>
      <description>&lt;p&gt;Originally published on Medium:&lt;br&gt;
&lt;a href="https://medium.com/@supsabhi/effortless-android-logging-with-timber-and-kotlin-f0aaa0a701b7" rel="noopener noreferrer"&gt;https://medium.com/@supsabhi/effortless-android-logging-with-timber-and-kotlin-f0aaa0a701b7&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Logging&lt;/strong&gt; is a cornerstone of Android development. It helps you track down bugs, monitor app behavior, and understand what’s happening under the hood-both during development and after your app is live. In short, logging is your best friend when coding!&lt;/p&gt;

&lt;p&gt;But let’s be honest: Android’s built-in Log class, while functional, can get unwieldy in bigger projects. Managing log tags, filtering output, and cleaning up before release can quickly become a headache.&lt;/p&gt;

&lt;p&gt;That’s where &lt;strong&gt;Timber&lt;/strong&gt; comes in-a lightweight, open-source logging library created by Jake Wharton that makes logging in Android (especially with Kotlin) much more pleasant.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Makes Timber Special?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Concise and Clean&lt;/strong&gt;: Timber’s API is simple and removes the need for repetitive boilerplate code.&lt;br&gt;
&lt;strong&gt;Automatic Tag Generation&lt;/strong&gt;: No more hardcoded tags-Timber automatically uses your class name as the tag&lt;br&gt;
&lt;strong&gt;Customizable Trees&lt;/strong&gt;: Timber introduces the concept of “trees,” which let you control how and where logs are output. For example, you can send logs to crash reporting tools or filter them by build type.&lt;br&gt;
&lt;strong&gt;Production Safety&lt;/strong&gt;: By default, Timber encourages you to disable logs in release builds, helping prevent sensitive information from leaking or cluttering production logs&lt;br&gt;
Setting Up Timber in Your Android App&lt;/p&gt;

&lt;p&gt;Step 1: Add the Dependency&lt;/p&gt;

&lt;p&gt;In your app-level build.gradle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;implementation 'com.jakewharton.timber:timber:5.0.1'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Check for the latest version before adding.)&lt;/p&gt;

&lt;p&gt;Step 2: Initialize Timber in Your Application Class&lt;/p&gt;

&lt;p&gt;The best place to “plant” your Timber trees is in your custom Application class. This ensures logging is set up as soon as your app starts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MyApp : Application() {
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
} else {
Timber.plant(ReleaseTree()) // Custom tree for release
}
}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DebugTree automatically tags logs with the calling class name, making debugging easier.&lt;br&gt;
For production, you can implement a custom ReleaseTree to filter or redirect logs as needed.&lt;br&gt;
Don’t forget to declare your Application class in the AndroidManifest.xml:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;application
android:name=".MyApp"
…&amp;gt;
&amp;lt;/application&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 3: Logging in Your Code&lt;/p&gt;

&lt;p&gt;Replace all usages of Log.d, Log.e, etc., with Timber’s methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Timber.d("Debug message")
Timber.i("Info message")
Timber.w("Warning message")
Timber.e("Error message: %s", error)
You can use string templates for dynamic content: Timber.d(“User id: $userId”).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All standard log levels (verbose, debug, info, warn, error) are supported.&lt;br&gt;
Advanced Usage: Custom Trees and Extensions&lt;/p&gt;

&lt;p&gt;Custom Trees&lt;/p&gt;

&lt;p&gt;Timber’s tree system lets you define how logs are handled. For example, you can create a tree that sends errors to Firebase Crashlytics or Sentry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class CrashReportingTree : Timber.Tree() {
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
if (priority &amp;gt;= Log.WARN) {
// Send to crash reporting
}
}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plant your custom tree in release builds to capture only important logs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kotlin Extensions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Libraries like &lt;strong&gt;timberkt&lt;/strong&gt; provide Kotlin-specific extensions, making logging even more idiomatic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Timber.d { "User id: $userId, name: ${user.name}" }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The lambda is only evaluated if the log will actually be printed, improving performance.&lt;br&gt;
Why Choose Timber?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No More Manual Tags&lt;/strong&gt;: Timber generates tags for you, so you don’t have to manage them manually.&lt;br&gt;
&lt;strong&gt;Easy Cleanup&lt;/strong&gt;: You can disable logging in release builds with a single line, so you never have to hunt down and remove log statements by hand.&lt;br&gt;
&lt;strong&gt;Customizable Behavior&lt;/strong&gt;: In production, you can route logs to crash reporting services instead of Logcat, ensuring you only capture what matters most.&lt;br&gt;
&lt;strong&gt;Automatic Metadata&lt;/strong&gt;: Timber can include class names, line numbers, and more, making your logs more informative.&lt;br&gt;
Final Thoughts&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Timber isn’t just another logging library-it’s a thoughtful enhancement to your Android development workflow.&lt;/strong&gt; With concise syntax, automatic tagging, and customizable trees, Timber makes logging a breeze without sacrificing control or safety.&lt;/p&gt;

&lt;p&gt;So next time you’re about to write Log.d(“TAG”, “Some message”), give Timber a try. It might just change the way you log forever.&lt;/p&gt;

&lt;p&gt;Happy Coding!&lt;/p&gt;

</description>
      <category>android</category>
      <category>kotlin</category>
      <category>timber</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Clean Architecture Made Simple: A Koin DI Walkthrough for Android</title>
      <dc:creator>supriya shah</dc:creator>
      <pubDate>Wed, 07 Jan 2026 08:30:13 +0000</pubDate>
      <link>https://forem.com/supriya_shah_1e9c3df6158c/clean-architecture-made-simple-a-koin-di-walkthrough-for-android-154a</link>
      <guid>https://forem.com/supriya_shah_1e9c3df6158c/clean-architecture-made-simple-a-koin-di-walkthrough-for-android-154a</guid>
      <description>&lt;p&gt;Originally published on Medium: &lt;br&gt;
&lt;a href="https://medium.com/@supsabhi/clean-architecture-made-simple-a-koin-di-walkthrough-for-android-c1f6fd95a718" rel="noopener noreferrer"&gt;https://medium.com/@supsabhi/clean-architecture-made-simple-a-koin-di-walkthrough-for-android-c1f6fd95a718&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Dependency injection (DI)&lt;/strong&gt; is a staple in modern Android development. Whether you’re a seasoned pro or just getting your feet wet, you’ve probably encountered DI’s benefits: loose coupling, modularity, reduced redundancy, and improved reusability. But the real magic of DI often reveals itself as your app grows in size and complexity-suddenly, managing dependencies by hand becomes a headache you didn’t see coming.&lt;/p&gt;

&lt;p&gt;At first, DI frameworks can seem intimidating. Many developers, when first introduced to DI, think, “Why do I need this extra layer? Isn’t it just making things more complicated?” And, to be fair, some DI frameworks do live up to that reputation-they can be complex and require a significant investment of time to learn and implement.&lt;/p&gt;

&lt;p&gt;But not all DI frameworks are created equal. If you’re looking for a straightforward, Kotlin-first solution, let me introduce you to Koin.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Koin&lt;/strong&gt; is a lightweight dependency injection framework designed specifically for Kotlin and Kotlin Multiplatform projects. Whether you’re building an Android app, a multiplatform project, or even a backend with Ktor, Koin has you covered. Developed by Kotzilla and a vibrant open-source community, Koin is known for its simplicity, minimal setup, and intuitive syntax.&lt;/p&gt;

&lt;p&gt;If you want to streamline your Android architecture with as little boilerplate as possible, Koin is an excellent choice. Let’s walk through how you can implement Koin in your next Android project.&lt;/p&gt;

&lt;p&gt;Step 1: Add Koin to Your Project&lt;br&gt;
First, add the Koin dependency to your app-level build.gradle file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;implementation "io.insert-koin:koin-android:3.5.3

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Be sure to check for the latest version before adding.)&lt;/p&gt;

&lt;p&gt;Step 2: Create Your Classes&lt;br&gt;
Let’s set up a simple example with a repository and a ViewModel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class LocationRepository {
    fun getLocation(): String = "Dubai"
}

class LocationViewModel(private val repository: LocationRepository) {
    fun getLocation() = repository.getLocation()
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 3: Define Koin Modules&lt;br&gt;
A Koin module tells the framework how to provide your dependencies. Here’s how you can define one for a network client, repository, and ViewModel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;val appModule = module {
    single { NetworkClient() }
    single { LocationRepository(get()) }
    viewModel { LocationViewModel(get()) }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;single creates a singleton instance.&lt;br&gt;
viewModel is a Koin extension for providing ViewModels.&lt;br&gt;
Step 4: Initialize Koin in Your Application Class&lt;br&gt;
Next, set up Koin in your Application class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        startKoin {
            androidContext(this@MyApp)
            modules(appModule)
        }
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And don’t forget to declare your custom Application class in your AndroidManifest.xml:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;application
    android:name=".MyApp"
    ... &amp;gt;
&amp;lt;/application&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 5: Inject Dependencies Where You Need Them&lt;br&gt;
Now, you can inject your dependencies directly into your Android components. For example, in an Activity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MainActivity : AppCompatActivity() {
private val viewModel: LocationViewModel by inject()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        println(viewModel.getLocation())
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Wrapping Up&lt;/strong&gt;&lt;br&gt;
Koin brings a modern, pragmatic approach to dependency injection in Android. Its concise syntax, absence of code generation, and seamless Kotlin integration make it a favorite for developers who value simplicity and maintainability. By following these steps, you can quickly set up Koin and enjoy cleaner, more modular code in your Android projects.&lt;/p&gt;

&lt;p&gt;Ready to take your architecture to the next level? Give Koin a try in your next Android app-you might just wonder how you ever coded without it.&lt;/p&gt;

&lt;p&gt;That’s all for now. Happy coding, and see you in the next article!&lt;/p&gt;

</description>
      <category>android</category>
      <category>kotlin</category>
      <category>development</category>
      <category>mobile</category>
    </item>
  </channel>
</rss>
