<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Marcello Galhardo</title><link>https://marcellogalhardo.dev/</link><description>Recent content on Marcello Galhardo</description><generator>Hugo -- 0.123.8</generator><language>en</language><copyright>CC BY-NC 4.0</copyright><lastBuildDate>Wed, 11 Mar 2026 18:51:00 +0100</lastBuildDate><atom:link href="https://marcellogalhardo.dev/index.xml" rel="self" type="application/rss+xml"/><item><title>Scoping ViewModels in Compose</title><link>https://marcellogalhardo.dev/posts/scoping-viewmodels-in-compose/</link><pubDate>Wed, 11 Mar 2026 18:51:00 +0100</pubDate><guid>https://marcellogalhardo.dev/posts/scoping-viewmodels-in-compose/</guid><description>Lifecycle ViewModel 2.11.0-alpha02 introduces rememberViewModelStoreOwner, an API to scope ViewModelStore directly within the Compose hierarchy.
Why It Matters Until now, ViewModelStore scoping was tied to navigation destinations, activities or fragments. There was no clean way to scope a ViewModel to an arbitrary part of your UI (such as a Pager page, a LazyList item, or a custom layout) without building your own ViewModelStoreOwner from scratch.
These new APIs close that gap:</description></item><item><title>NavigationEvent Info</title><link>https://marcellogalhardo.dev/posts/navigation-event-info/</link><pubDate>Sat, 01 Nov 2025 22:22:22 +2222</pubDate><guid>https://marcellogalhardo.dev/posts/navigation-event-info/</guid><description>NavigationEvent is a Kotlin Multiplatform library for handling system gestures - back and forward - on all platforms. It works on Android, iOS and Desktop with Web support coming next.
Android rely on OnBackPressedDispatcher from androidx.activity. It handles back presses, and that was enough. But once you target more than Android, you also need forward navigation - like on the web.
That&amp;rsquo;s why NavigationEvent exists: one event system that works everywhere.</description></item><item><title>IDEA Vim</title><link>https://marcellogalhardo.dev/posts/idea-vim/</link><pubDate>Tue, 16 Sep 2025 11:27:02 +0100</pubDate><guid>https://marcellogalhardo.dev/posts/idea-vim/</guid><description>I&amp;rsquo;ve been using the IDEA Vim plugin in Android Studio for a while. I only ever learned the basics with Practical Vim, but that&amp;rsquo;s been enough.
The nice part is how the same muscle memory works everywhere: I can edit the same way in Android Studio, VS Code, iTerm, or Obsidian. Most editor-specific shortcuts I used to know are gone, and I don’t miss them.
IDEA Vim config Here’s my .</description></item><item><title>Unit Testing ViewModels</title><link>https://marcellogalhardo.dev/posts/unit-testing-viewmodels/</link><pubDate>Sat, 22 Feb 2025 22:22:22 +2222</pubDate><guid>https://marcellogalhardo.dev/posts/unit-testing-viewmodels/</guid><description>Lifecycle 2.9.0-alpha01 introduced ViewModelScenario, a helper that simplifies unit testing for ViewModels.
Why It Matters You can test a ViewModel by simply creating an instance using its constructor in your test code. However, this approach has limitations — there is no straightforward way to:
Trigger ViewModelStore.clear()/ViewModel.onCleared(). Simulate a save and restore instance state. With ViewModelScenario, these are now easy to test, helping you catch errors related to ViewModel clean-up and saved state.</description></item><item><title>Function Properties in Data Classes are Code Smells</title><link>https://marcellogalhardo.dev/posts/function-properties-in-data-classes-are-code-smells/</link><pubDate>Fri, 29 Nov 2024 16:09:00 +0100</pubDate><guid>https://marcellogalhardo.dev/posts/function-properties-in-data-classes-are-code-smells/</guid><description>To me, using functions as properties in the primary constructor of a data class is a code smell. Here&amp;rsquo;s why:
Data classes represent data. Data is a value. Data is never executed. Functions are not data. They produce values when executed. Note: By the book, a function returns a value, while a procedure executes commands. In both cases, neither is data.
Why It Matters Kotlin generates key methods for data classes based on the properties in the primary constructor, such as:</description></item><item><title>Robolectric in commonTest</title><link>https://marcellogalhardo.dev/posts/robolectric-in-common-test/</link><pubDate>Thu, 28 Nov 2024 16:15:00 +0100</pubDate><guid>https://marcellogalhardo.dev/posts/robolectric-in-common-test/</guid><description>Sharing tests across Kotlin Multiplatform (KMP) projects can be tricky when dealing with platform-specific APIs like Android&amp;rsquo;s Bundle. commonTest on Android relies on the androidTest source set, which uses an empty android.jar, leading to test failures.
The Solution The ideal solution is to avoid platform-specific APIs in commonTest.
If that’s not an option, you can use Robolectric in your commonTest source set to access functional Android classes. This approach:
Allows testing of platform-specific code in commonTest.</description></item><item><title>Extension Shadowing for Actual Declarations in KMP</title><link>https://marcellogalhardo.dev/posts/extension-shadowing-for-actual-declarations-in-kmp/</link><pubDate>Thu, 07 Nov 2024 15:49:00 +0100</pubDate><guid>https://marcellogalhardo.dev/posts/extension-shadowing-for-actual-declarations-in-kmp/</guid><description>Heads-up: this article assumes familiarity with Kotlin&amp;rsquo;s extension functions and expect and actual declarations in Kotlin Multiplatform (KMP).
My work has recently focused on &amp;ldquo;commonizing&amp;rdquo;1 APIs, and I came across KT-70012, which I believe merits attention.
In Kotlin JVM development, the EXTENSION_SHADOWED_BY_MEMBER warning indicates that an extension function is redundant, as it will always be overshadowed by a member function with the same name when invoked. However, in KMP, this behaviour can be useful, as shadowing may occur on some platforms but not all.</description></item><item><title>No Mocks Allowed</title><link>https://marcellogalhardo.dev/posts/no-mocks-allowed/</link><pubDate>Wed, 28 Jun 2023 18:34:00 +0100</pubDate><guid>https://marcellogalhardo.dev/posts/no-mocks-allowed/</guid><description>Disclaimer: It has been brought to my attention the title can be seen as a click bait. That wasn&amp;rsquo;t my intention and I&amp;rsquo;m sorry. I wanted to reference the Fallout game series and the No Mutants Allowed community.
Testable code plays a crucial role in app development. When we neglect designing code for testability, we often resort to using a mock library (such as Mockito Kotlin, also know as “auto-mockers”) as a mean to achieve test coverage.</description></item><item><title>Injection Points</title><link>https://marcellogalhardo.dev/posts/injection-points/</link><pubDate>Fri, 02 Jun 2023 09:12:00 +0100</pubDate><guid>https://marcellogalhardo.dev/posts/injection-points/</guid><description>Android has made significant progress in becoming a DI-Friendly Framework. Throughout the years, new APIs like AppComponentFactory and FragmentFactory have been introduced, allowing apps to incorporate their own custom constructors and facilitating the development of testable code.
The purpose of this article is to highlight some of the Android APIs that are utilised behind the scenes. By exploring these APIs, developers can gain a better understanding of the underlying mechanisms employed by popular libraries (such as Dagger Hilt and Koin Android).</description></item><item><title>Namespace for Extension Functions</title><link>https://marcellogalhardo.dev/posts/2023/namespace-for-extension-functions/</link><pubDate>Sat, 25 Mar 2023 09:02:50 +0100</pubDate><guid>https://marcellogalhardo.dev/posts/2023/namespace-for-extension-functions/</guid><description>A few weeks ago, I had to create an extension function - a usual task for any Kotlin developer. But there were a few limitations:
The receiver was a common type, polluted with too many methods. The extension function was only relevant to my feature package. Creating a Gradle module was out of scope. Introducing a new type to hold the function felt like too much. Kotlin doesn&amp;rsquo;t support package-private, yet.</description></item><item><title>Trampoline Activities</title><link>https://marcellogalhardo.dev/posts/2023/trampoline-activities/</link><pubDate>Mon, 06 Mar 2023 09:02:50 +0100</pubDate><guid>https://marcellogalhardo.dev/posts/2023/trampoline-activities/</guid><description>Today, I came across the term &amp;ldquo;Trampoline Activities&amp;rdquo;. Although it&amp;rsquo;s not an official name (or is it?), I&amp;rsquo;ve noticed it is a typical pattern and have decided to make a &amp;ldquo;How To&amp;rdquo; guide.
What are Trampoline Activities? A Trampoline Activity is an Activity that launches another activity and finishes itself. It may include conditional logic to determine which activity to launch or transforming the parameters before sending it to the next Activity.</description></item><item><title>Deep Models</title><link>https://marcellogalhardo.dev/posts/2021/10/07/deep-models/</link><pubDate>Thu, 07 Oct 2021 09:02:50 +0100</pubDate><guid>https://marcellogalhardo.dev/posts/2021/10/07/deep-models/</guid><description>Modeling is a critical task in Software Development: good models reduce the risk of bugs, increase readability and improve maintainability. However, we can often see developers focusing on &amp;ldquo;How can I code this?&amp;rdquo;, and they are done with their task when they find a way to code it. This inherently reduces the domain modeling to the abuse of primitives and shallow design where any inconsistent state is allowed.
To better explain, let&amp;rsquo;s consider the hypothetical requirements:</description></item><item><title>Using Compose Beta on AS 4.1</title><link>https://marcellogalhardo.dev/posts/2021/03/30/using-compose-beta-on-as-4-1/</link><pubDate>Tue, 30 Mar 2021 17:37:41 +0200</pubDate><guid>https://marcellogalhardo.dev/posts/2021/03/30/using-compose-beta-on-as-4-1/</guid><description>Jetpack Compose hit Beta! Many teams are excited to experiment with Compose, but as you might know, since 1.0.0-alpha04, the compiler has been refactored to a new group and became incompatible with the current Android Studio (AS) 4.1 stable:
Compose Version 1.0.0-alpha04 is only compatible with Android Studio 4.2 Canary 13 and later.
Been forced to use a Canary version of AS is a real bummer. There are cases in which you want to explore Compose in a real-world application (e.</description></item><item><title>N26 Path to Anvil</title><link>https://marcellogalhardo.dev/posts/2021/02/05/n26-path-to-anvil/</link><pubDate>Fri, 05 Feb 2021 09:02:50 +0100</pubDate><guid>https://marcellogalhardo.dev/posts/2021/02/05/n26-path-to-anvil/</guid><description>This post represents my personal experience while working at N26. I do not speak for the company nor by other employees.
N26 Android App current codebase has a million lines of code, 280+ modules, and 30+ engineers working in 4 different countries and different timezones in a mono repository. Our modules are divided into features and libraries, and we have been using &amp;ldquo;Sample Apps&amp;rdquo; for years now as our full app build time might take up to 20 minutes.</description></item><item><title>Humble Views, Proud ViewModels</title><link>https://marcellogalhardo.dev/posts/2021/02/01/humble-views-proud-viewmodels/</link><pubDate>Mon, 01 Feb 2021 09:02:50 +0100</pubDate><guid>https://marcellogalhardo.dev/posts/2021/02/01/humble-views-proud-viewmodels/</guid><description>The Android Community has long advocated that Activities and Fragments were views - but this perception has changed over time. For good. Let&amp;rsquo;s dive deep into how to design views and view models, how they wire to a LifecycleOwner, and how this can positively impact your&amp;rsquo;s app testability.
To better describe how to build humble views we will be developing an elementary Sign-Up form with an email, a password text field and two buttons: a cancel that pops the user&amp;rsquo;s back stack and a sign up that creates an account and moves the user to the home screen.</description></item><item><title>Naming Factory Methods</title><link>https://marcellogalhardo.dev/posts/2020/02/01/naming-factory-methods/</link><pubDate>Sat, 01 Feb 2020 09:02:50 +0100</pubDate><guid>https://marcellogalhardo.dev/posts/2020/02/01/naming-factory-methods/</guid><description>When discussing Factory Methods, extension functions are often preferred in Kotlin. However, naming these functions in a discoverable way without cluttering your project&amp;rsquo;s namespace can be challenging. A great source of inspiration is Kotlin&amp;rsquo;s Standard Library, which offers numerous examples to guide function design.
Wrapping an Instance If you want to take an existing instance and adapt it to a different object to meet another contract—such as creating a ViewModelProvider.Factory that internally uses a javax.</description></item><item><title>About</title><link>https://marcellogalhardo.dev/about/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://marcellogalhardo.dev/about/</guid><description>Software engineer with over 10 years of experience. I have been building software professionally since 2012, starting on Web and Backend, later on Desktop, and finally, on Android. I worked with small teams at Quandoo, to dozens of engineers working on the same codebase at N26 and Delivery Hero. At N26, I worked on the Consumer App and later led the Android Platform Team. The apps I worked on had millions of downloads used in more than 20 countries.</description></item><item><title>Talks</title><link>https://marcellogalhardo.dev/talks/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://marcellogalhardo.dev/talks/</guid><description> September 25, 2025: Custom Codecs with KotlinX Serialization (Droidcon Berlin) May 23, 2025: Lessons learned decoupling Architecture Components from platform specific code (KotlinConf) September 6, 2024: Lifecycle path to Multiplaform (Droidcon Lisbon) August 9, 2024: Lifecycle path to Multiplatform (Android Developers) July 4, 2024: Lifecycle path to Multiplatform (Droidcon Berlin) April 29, 2021: Anvil na Prática (PT-BR) June 05, 2019: Railway Oriented Programming with Kotlin April 17, 2019: Effective Kotlin March 01, 2019: Modularizing Legacy Apps November 11, 2018: Android Modular Architecture January 24, 2017: Introduction to Dagger 2 January 24, 2017: Introdução ao Dagger 2 (PT-BR) September 06, 2016: SOLID no Android 2 (PT-BR)</description></item><item><title>Uses</title><link>https://marcellogalhardo.dev/uses/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://marcellogalhardo.dev/uses/</guid><description>Software App Launcher: Alfred Keyboard Navigation: Shortcat Window Manager: Magnet Window Switcher: Contexts Menu Bar Manager: Barbee File Manager: Marta IDE: IntelliJ IDEA Diagrams, Work: PlantUML Diagrams, Personal: Diagrams Note-taking, Work: Obsidian Note-taking, Personal: UpNote Hardware Computer: 2020 16&amp;quot; Macbook Pro Keyboard: Ultimate Hacking Keyboard v2 Mouse: Logitech MX Master 3s Ergonomics Chair: JÄRVFJÄLLET</description></item></channel></rss>