<?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>DEV Community: Danilo Barreto</title>
    <description>The latest articles on DEV Community by Danilo Barreto (@dgbarreto).</description>
    <link>https://dev.to/dgbarreto</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F616095%2F76563b89-e1da-4ddd-a515-9189634bea08.jpeg</url>
      <title>DEV Community: Danilo Barreto</title>
      <link>https://dev.to/dgbarreto</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dgbarreto"/>
    <language>en</language>
    <item>
      <title>Building a Design System That Actually Gets Used: Tokens, Components, and the AGP 9 Gotcha That Almost Broke It</title>
      <dc:creator>Danilo Barreto</dc:creator>
      <pubDate>Tue, 21 Jul 2026 00:37:09 +0000</pubDate>
      <link>https://dev.to/dgbarreto/building-a-design-system-that-actually-gets-used-tokens-components-and-the-agp-9-gotcha-that-1hh1</link>
      <guid>https://dev.to/dgbarreto/building-a-design-system-that-actually-gets-used-tokens-components-and-the-agp-9-gotcha-that-1hh1</guid>
      <description>&lt;h1&gt;
  
  
  Building a Design System That Actually Gets Used: Tokens, Components, and the AGP 9 Gotcha That Almost Broke It
&lt;/h1&gt;

&lt;p&gt;A design system is only as good as its adoption rate. It's easy to publish a beautiful &lt;code&gt;FinioButton&lt;/code&gt; component and watch half the codebase quietly reach for raw &lt;code&gt;Material3&lt;/code&gt; &lt;code&gt;Button&lt;/code&gt; anyway because it was faster in the moment. The real engineering problem isn't drawing the components — it's making the design system the path of least resistance.&lt;/p&gt;

&lt;p&gt;Here's how &lt;code&gt;finio-design-system&lt;/code&gt;, one of five KMP libraries behind the Finio personal finance app, is structured to make that true, plus a packaging bug that silently strips your design system's resources out of production builds if you don't know to look for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tokens first, components second
&lt;/h2&gt;

&lt;p&gt;Everything in the design system is built on four token categories, each its own object in &lt;code&gt;dev.finio.designsystem.theme&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Colors&lt;/strong&gt; (&lt;code&gt;FinioColors.kt&lt;/code&gt;) — semantic, not literal. &lt;code&gt;primary = #6C63FF&lt;/code&gt;, but also purpose-built tokens like &lt;code&gt;success = #4CAF50&lt;/code&gt;, &lt;code&gt;error = #B00020&lt;/code&gt;, &lt;code&gt;subtle = #8A8AA8&lt;/code&gt;, &lt;code&gt;disabled&lt;/code&gt; / &lt;code&gt;onDisabled&lt;/code&gt; pairs. The naming convention pairs every "on-X" color with its background (&lt;code&gt;onPrimary&lt;/code&gt;, &lt;code&gt;onSurface&lt;/code&gt;, &lt;code&gt;onError&lt;/code&gt;), following the same pattern Material Design uses internally — which makes the token set easy to reason about even if you've never seen Finio's code before.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spacing&lt;/strong&gt; (&lt;code&gt;FinioSpacing.kt&lt;/code&gt;) — a linear scale from &lt;code&gt;xxxs = 2.dp&lt;/code&gt; to &lt;code&gt;xxxl = 64.dp&lt;/code&gt;, in nine steps. Having nine named steps instead of arbitrary &lt;code&gt;dp&lt;/code&gt; values everywhere means a spacing audit is a search for raw &lt;code&gt;.dp&lt;/code&gt; literals, not a design review.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Typography&lt;/strong&gt; (&lt;code&gt;FinioTypography.kt&lt;/code&gt;) — a full type scale from &lt;code&gt;displayLarge&lt;/code&gt; (57sp) down to &lt;code&gt;labelSmall&lt;/code&gt; (11sp), each with explicit &lt;code&gt;lineHeight&lt;/code&gt; and &lt;code&gt;letterSpacing&lt;/code&gt;, mirroring Material 3's type scale but scoped to the app's own object so it can diverge later without touching Material internals.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shape&lt;/strong&gt; (&lt;code&gt;FinioShape.kt&lt;/code&gt;) — seven corner radius steps from &lt;code&gt;none&lt;/code&gt; to &lt;code&gt;full&lt;/code&gt; (a pill shape via &lt;code&gt;RoundedCornerShape(50)&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The rule enforced across the entire &lt;code&gt;finio-app&lt;/code&gt; codebase: &lt;strong&gt;no screen uses a hardcoded color, spacing, shape, or raw Material3 component.&lt;/strong&gt; Every value traces back to one of these four token objects, and every interactive element is a DS component (&lt;code&gt;FinioButton&lt;/code&gt;, &lt;code&gt;FinioTextField&lt;/code&gt;, &lt;code&gt;FinioCard&lt;/code&gt;) rather than &lt;code&gt;Button&lt;/code&gt;, &lt;code&gt;OutlinedTextField&lt;/code&gt;, or &lt;code&gt;Card&lt;/code&gt; directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Designing components around variants, not props explosion
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;FinioButton&lt;/code&gt; is a useful example of API design under constraint:&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;FinioButton&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="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&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="nc"&gt;Modifier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;FinioButtonVariant&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FinioButtonVariant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Primary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FinioButtonVariant&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;Primary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Secondary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Destructive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Ghost&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Internally, &lt;code&gt;FinioButton&lt;/code&gt; dispatches to &lt;code&gt;FinioPrimaryButton&lt;/code&gt;, &lt;code&gt;FinioSecondayButton&lt;/code&gt; (yes, that typo is load-bearing now — renaming it is a breaking API change for existing call sites, a reminder that public API surfaces accumulate small debts you choose to live with), &lt;code&gt;FinioDestructiveButton&lt;/code&gt;, and &lt;code&gt;FinioGhostButton&lt;/code&gt;. Each of those internal implementations pulls its colors, shape, and typography from tokens — &lt;code&gt;FinioColors.primary&lt;/code&gt; / &lt;code&gt;onPrimary&lt;/code&gt; for the primary variant, &lt;code&gt;FinioColors.error&lt;/code&gt; for destructive, &lt;code&gt;FinioShape.sm&lt;/code&gt;, &lt;code&gt;FinioTypography.labelLarge&lt;/code&gt; throughout.&lt;/p&gt;

&lt;p&gt;The pattern generalizes across the component set:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;FinioCardTransaction&lt;/code&gt; encodes an &lt;code&gt;enum class FinioTransactionType { Income, Expense }&lt;/code&gt; and maps it directly to &lt;code&gt;FinioColors.success&lt;/code&gt; / &lt;code&gt;FinioColors.error&lt;/code&gt; for the amount text — so "is this money coming in or going out" is a type-level decision, not a color chosen ad hoc at each call site.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FinioText&lt;/code&gt; ships as semantic wrappers (&lt;code&gt;FinioHeadline&lt;/code&gt;, &lt;code&gt;FinioBody&lt;/code&gt;, &lt;code&gt;FinioLabel&lt;/code&gt;) rather than exposing raw &lt;code&gt;Text(style = ...)&lt;/code&gt; calls, so a copy change to "what does body text look like app-wide" is one edit, not a find-and-replace across every screen.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FinioDialog&lt;/code&gt; bundles the interaction pattern itself (&lt;code&gt;isDestructive: Boolean&lt;/code&gt; swaps the confirm button to the &lt;code&gt;Destructive&lt;/code&gt; variant automatically) so a screen author can't accidentally ship a "delete this transaction" dialog with a primary-colored confirm button.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The common thread: the component API encodes the &lt;em&gt;decision&lt;/em&gt; (is this a destructive action? is this income or expense?), and the token/variant mapping happens once, inside the design system, instead of being re-derived by every screen that needs it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The AGP 9 packaging bug that ships an app with no design system resources
&lt;/h2&gt;

&lt;p&gt;This is the kind of bug that doesn't show up until it's too late to catch in a code review: on AGP 9.x with &lt;code&gt;com.android.kotlin.multiplatform.library&lt;/code&gt;, Compose resources (&lt;code&gt;composeResources&lt;/code&gt;) are &lt;strong&gt;excluded from the published &lt;code&gt;.aar&lt;/code&gt; by default&lt;/strong&gt; unless you explicitly opt in:&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="nf"&gt;androidLibrary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;androidResources&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;enable&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&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;Without this line, &lt;code&gt;finio-design-system&lt;/code&gt; builds fine locally, publishes fine to GitHub Packages, and then throws &lt;code&gt;MissingResourceException&lt;/code&gt; at runtime in &lt;code&gt;finio-app&lt;/code&gt; — but only for whatever resources the design system bundles (icons, fonts) that got silently dropped from the artifact. It's a gap between "the library compiles" and "the library actually works when consumed," and it only surfaces once you try to run the consuming app, not when you build the library itself.&lt;/p&gt;

&lt;p&gt;If you're on AGP 9 with a KMP library module and you see resource-not-found exceptions that make no sense given the resource clearly exists in the source tree, check this flag first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making adoption the easy path, not the enforced path
&lt;/h2&gt;

&lt;p&gt;None of the token discipline above is enforced by a linter in Finio yet — it's a convention, reinforced by code review and by the fact that DS components are simply less code to write than reaching for Material3 directly and re-deriving colors and spacing by hand. That's a deliberate bet: a design system wins when using it correctly is less typing than not using it, not only when a CI check blocks the PR. The next step on the roadmap is exactly the enforcement layer — extracting &lt;code&gt;FinioNavigationBar&lt;/code&gt; as a standalone DS component instead of leaving it inlined in the app shell, and adding semantic income/expense color tokens to &lt;code&gt;FinioTheme&lt;/code&gt; to eliminate the last hardcoded &lt;code&gt;Color(0xFF2E7D32)&lt;/code&gt; / &lt;code&gt;Color(0xFFC62828)&lt;/code&gt; pair still living in &lt;code&gt;TransactionItem&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Build the token layer (color, spacing, typography, shape) before the component layer — components should consume tokens, never define values themselves.&lt;/li&gt;
&lt;li&gt;Encode decisions in the component API (destructive vs. primary, income vs. expense) rather than leaving color/style choices to whoever writes the screen.&lt;/li&gt;
&lt;li&gt;On AGP 9.x KMP library modules, explicitly enable &lt;code&gt;androidResources&lt;/code&gt; or your published artifact silently loses its bundled resources.&lt;/li&gt;
&lt;li&gt;Treat every hardcoded color or raw Material3 usage found in review as a design system gap to close, not a one-off exception to allow.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;em&gt;This article is part of a series on the engineering decisions behind Finio, a Kotlin Multiplatform personal finance app. Full series and notes: &lt;a href="https://github.com/dgbarreto/tech-writing" rel="noopener noreferrer"&gt;github.com/dgbarreto/tech-writing&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>androiddev</category>
      <category>compose</category>
      <category>designsystem</category>
      <category>kotlin</category>
    </item>
    <item>
      <title>Structuring a Kotlin Multiplatform App as a Library Ecosystem: Lessons from Building Finio</title>
      <dc:creator>Danilo Barreto</dc:creator>
      <pubDate>Sat, 11 Jul 2026 21:18:19 +0000</pubDate>
      <link>https://dev.to/dgbarreto/structuring-a-kotlin-multiplatform-app-as-a-library-ecosystem-lessons-from-building-finio-4f95</link>
      <guid>https://dev.to/dgbarreto/structuring-a-kotlin-multiplatform-app-as-a-library-ecosystem-lessons-from-building-finio-4f95</guid>
      <description>&lt;h1&gt;
  
  
  Structuring a Kotlin Multiplatform App as a Library Ecosystem: Lessons from Building Finio
&lt;/h1&gt;

&lt;p&gt;When most tutorials talk about Kotlin Multiplatform (KMP), they show you a single repo with a &lt;code&gt;shared&lt;/code&gt; module and call it a day. That works for a demo. It falls apart the moment you're building a real product with a backend team, a design system that needs to evolve independently, and features that ship on different cadences.&lt;/p&gt;

&lt;p&gt;While building &lt;strong&gt;Finio&lt;/strong&gt;, a personal finance app for Android and iOS, I split the codebase into six repositories instead of one monolith: a Node.js/TypeScript API, five independently published KMP library modules, and a Compose Multiplatform app shell that consumes all of them. Here's why, and what it actually takes to make that work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The shape of the ecosystem
&lt;/h2&gt;

&lt;p&gt;Finio is composed of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;finio-api&lt;/code&gt;&lt;/strong&gt; — a Node.js/TypeScript backend on Railway. Routes live inside feature modules (&lt;code&gt;src/modules/budget&lt;/code&gt;, &lt;code&gt;src/modules/transaction&lt;/code&gt;, etc.) rather than a separate &lt;code&gt;routes/&lt;/code&gt; folder, and request/response contracts are validated with Zod schemas in &lt;code&gt;src/schemas/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Five KMP library modules&lt;/strong&gt;, each published independently via Maven to GitHub Packages: &lt;code&gt;finio-design-system&lt;/code&gt;, &lt;code&gt;finio-auth&lt;/code&gt;, &lt;code&gt;finio-transaction&lt;/code&gt;, &lt;code&gt;finio-budget&lt;/code&gt;, &lt;code&gt;finio-insights&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;finio-app&lt;/code&gt;&lt;/strong&gt; — the Compose Multiplatform shell, split into &lt;code&gt;androidApp&lt;/code&gt;, &lt;code&gt;iosApp&lt;/code&gt;, &lt;code&gt;sharedLogic&lt;/code&gt;, and &lt;code&gt;sharedUI&lt;/code&gt;, which pulls in every library module as a dependency.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The app shell doesn't own business logic. It owns navigation, composition, and platform wiring (Koin DI graph, FCM registration, deep link handling). Everything else — auth flows, transaction parsing, budget calculations, insights — lives in a module that can be versioned, tested, and consumed on its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why split it this way
&lt;/h2&gt;

&lt;p&gt;The obvious question: why not just use Gradle's multi-module setup inside one repo? Two reasons drove the decision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Independent versioning.&lt;/strong&gt; When &lt;code&gt;finio-auth&lt;/code&gt; gets a bug fix, I don't want to force a new release of &lt;code&gt;finio-budget&lt;/code&gt; or touch anything in the app shell's build graph. Publishing each module as its own Maven artifact means &lt;code&gt;finio-app&lt;/code&gt;'s &lt;code&gt;build.gradle.kts&lt;/code&gt; just bumps a version string:&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="nf"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"dev.finio:auth:1.4.2"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"dev.finio:transaction:2.1.0"&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;Forcing a real API boundary.&lt;/strong&gt; When a module only exists as source inside a monorepo, it's tempting to reach across module boundaries "just this once." When a module is a compiled artifact pulled from GitHub Packages, that's not possible — you're forced to design a public API surface deliberately, the same discipline you'd apply to any external SDK.&lt;/p&gt;

&lt;p&gt;The tradeoff is real: cross-module changes now require publishing a new version and bumping it downstream, which is slower than editing a file in a monorepo. For a solo/small-team project this is a deliberate cost, taken on because it mirrors how larger organizations actually structure multiplatform codebases once more than one team touches the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;build.gradle.kts&lt;/code&gt; template that makes this repeatable
&lt;/h2&gt;

&lt;p&gt;Every KMP library module in Finio follows the same Gradle template, based on &lt;code&gt;finio-design-system&lt;/code&gt;. A few details matter more than they look:&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="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;localProperties&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="c1"&gt;// read before the plugins block&lt;/span&gt;
&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;publishVersion&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="nf"&gt;plugins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;libs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kotlinMultiplatform&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// must come before androidMultiplatformLibrary&lt;/span&gt;
    &lt;span class="nf"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;libs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;androidMultiplatformLibrary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"maven-publish"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;kotlin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;androidLibrary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;iosArm64&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;iosSimulatorArm64&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nf"&gt;listOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;iosArm64&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;iosSimulatorArm64&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;forEach&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;binaries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;framework&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;baseName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"auth"&lt;/span&gt; &lt;span class="c1"&gt;// matches the internal module name — see below&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="c1"&gt;// publishing block lives OUTSIDE the kotlin { } block&lt;/span&gt;
&lt;span class="nf"&gt;publishing&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;publications&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MavenPublication&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;groupId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"dev.finio"&lt;/span&gt;
        &lt;span class="n"&gt;artifactId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
        &lt;span class="c1"&gt;// pom { ... }&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;repositories&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;maven&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;credentials&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GITHUB_ACTOR"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
                &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GITHUB_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&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="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;Two ordering rules aren't cosmetic: the &lt;code&gt;kotlinMultiplatform&lt;/code&gt; plugin has to be applied before &lt;code&gt;androidMultiplatformLibrary&lt;/code&gt;, and the &lt;code&gt;publishing&lt;/code&gt; block has to sit outside the &lt;code&gt;kotlin { }&lt;/code&gt; block. Get either wrong and you get Gradle configuration errors that don't obviously point back to ordering.&lt;/p&gt;

&lt;h2&gt;
  
  
  The naming trap: internal module name vs. artifact ID
&lt;/h2&gt;

&lt;p&gt;The single most expensive lesson from this project: &lt;strong&gt;the internal module name determines the generated iOS framework/artifact ID&lt;/strong&gt;, and it has to match the domain, not be something generic like &lt;code&gt;shared&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Early on, &lt;code&gt;finio-auth&lt;/code&gt;'s internal module was named &lt;code&gt;shared&lt;/code&gt; — a leftover from scaffolding. That name propagated into the generated iOS artifact ID, producing a framework that didn't clearly correspond to what it was (auth), and colliding conceptually with any other module that also defaulted to &lt;code&gt;shared&lt;/code&gt;. The same issue showed up in &lt;code&gt;finio-transaction&lt;/code&gt;, where the Android artifact was published as &lt;code&gt;dev.finio:finio-transaction-android&lt;/code&gt; instead of the intended &lt;code&gt;dev.finio:transaction-android&lt;/code&gt; — traced back to the &lt;code&gt;artifactId&lt;/code&gt; assignment inside &lt;code&gt;withType&amp;lt;MavenPublication&amp;gt;&lt;/code&gt; not matching &lt;code&gt;project.name&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The fix in both cases was the same: rename the internal module to match its domain (&lt;code&gt;auth&lt;/code&gt;, &lt;code&gt;transactions&lt;/code&gt;) and verify the &lt;code&gt;artifactId&lt;/code&gt; block explicitly rather than relying on Gradle defaults. If you're setting up a similar structure, check this on day one — renaming a published artifact after consumers depend on it is a breaking change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this leaves the app shell
&lt;/h2&gt;

&lt;p&gt;Because business logic lives in versioned libraries, &lt;code&gt;finio-app&lt;/code&gt; stays thin: Compose screens, Voyager navigation, Koin wiring, and platform-specific glue (push notification registration, deep link routing). Before wiring a new feature into the shell, the practice that's paid off is a &lt;strong&gt;DTO contract review&lt;/strong&gt; — checking that the fields a KMP module expects (e.g., &lt;code&gt;finio-transaction&lt;/code&gt;, &lt;code&gt;finio-budget&lt;/code&gt;) actually match what &lt;code&gt;finio-api&lt;/code&gt;'s Zod schemas return, before writing a single line of UI code against them. Contract mismatches caught at this stage are a diff; caught after UI is built, they're a rewrite.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;p&gt;If you're structuring a KMP product for more than a weekend project:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Treat each domain (auth, transactions, budget) as a library with a real public API, not a folder.&lt;/li&gt;
&lt;li&gt;Get the internal module naming right before you publish — it leaks into iOS artifact IDs and is expensive to rename later.&lt;/li&gt;
&lt;li&gt;Keep the &lt;code&gt;publishing&lt;/code&gt; block and plugin ordering consistent across every module via a shared template; copy-pasting Gradle config by hand invites drift.&lt;/li&gt;
&lt;li&gt;Validate backend/client contracts before building UI on top of them, not after.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;None of this is exotic — it's the same modular discipline backend teams have applied to microservices for years, applied to a mobile codebase that happens to target two platforms from one Kotlin source tree.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article is part of a series on the engineering decisions behind Finio, a Kotlin Multiplatform personal finance app. Full series and notes: &lt;a href="https://github.com/dgbarreto/tech-writing" rel="noopener noreferrer"&gt;github.com/dgbarreto/tech-writing&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>kmp</category>
      <category>androiddev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Contratos no Kotlin</title>
      <dc:creator>Danilo Barreto</dc:creator>
      <pubDate>Mon, 15 Jul 2024 20:49:24 +0000</pubDate>
      <link>https://dev.to/dgbarreto/contratos-no-kotlin-4k56</link>
      <guid>https://dev.to/dgbarreto/contratos-no-kotlin-4k56</guid>
      <description>&lt;p&gt;No desenvolvimento Android com Kotlin, um dos recursos avançados disponíveis para melhorar a segurança e a robustez do código são os "contracts". Contracts permitem que desenvolvedores definam condições que devem ser atendidas antes ou depois da execução de uma função. Este artigo explorará o conceito de contracts, sua importância, como utilizá-los e os benefícios que eles trazem para o desenvolvimento Android.&lt;/p&gt;

&lt;h2&gt;
  
  
  O Que São Contracts?
&lt;/h2&gt;

&lt;p&gt;Contracts em Kotlin são declarações que definem condições para a execução de funções. Eles permitem que você especifique pré-condições e pós-condições que o compilador pode usar para otimizações e verificações de segurança. Isso ajuda a garantir que certas condições sejam verdadeiras em pontos específicos do código, melhorando a segurança em tempo de compilação e a legibilidade do código.&lt;/p&gt;

&lt;h2&gt;
  
  
  Importância dos Contracts
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Segurança em Tempo de Compilação&lt;br&gt;
Contracts permitem que o compilador faça verificações adicionais, ajudando a capturar erros mais cedo no ciclo de desenvolvimento.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Código Mais Claro e Direto&lt;br&gt;
Especificar pré-condições e pós-condições torna o código mais legível e documentado, facilitando o entendimento das expectativas de uma função.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Redução de Erros em Tempo de Execução&lt;br&gt;
Ao garantir que certas condições sejam atendidas antes de executar um bloco de código, você reduz a chance de erros em tempo de execução, como NullPointerException.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Exemplo de Uso de Contracts
&lt;/h2&gt;

&lt;p&gt;Vamos explorar um exemplo prático de como usar contracts em uma função Kotlin. Suponha que estamos desenvolvendo uma função de validação para um objeto Request.&lt;/p&gt;

&lt;p&gt;Definindo um Contract&lt;br&gt;
Aqui está um exemplo de função de validação que usa um contract para garantir que o objeto Request e seu argumento não sejam nulos:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Explicação do Código
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Importação de Contracts:&lt;/strong&gt;&lt;br&gt;
O contrato é uma funcionalidade experimental no Kotlin, por isso é necessário importar o módulo kotlin.contracts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definição do Contract:&lt;/strong&gt;&lt;br&gt;
Dentro da função validate, usamos o bloco contract para definir as condições que devem ser verdadeiras para que a função retorne normalmente. Aqui, especificamos que a função só retorna (returns()) se request e request.arg não forem nulos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Validação das Condições:&lt;/strong&gt;&lt;br&gt;
A seguir, realizamos verificações explícitas. Se request for nulo, lançamos uma exceção. Se request.arg for nulo ou vazio, também lançamos uma exceção.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefícios dos Contracts
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Verificação Adiantada&lt;/strong&gt;&lt;br&gt;
Ao definir contratos, o compilador pode verificar essas condições durante a compilação, ajudando a identificar possíveis problemas mais cedo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Melhor Documentação do Código&lt;/strong&gt;&lt;br&gt;
O uso de contracts torna o código mais auto-documentado, esclarecendo quais condições são esperadas para a execução correta da função.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Maior Robustez&lt;/strong&gt;&lt;br&gt;
Garantir que pré-condições sejam atendidas antes da execução de um bloco de código reduz a possibilidade de falhas inesperadas durante a execução.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;O uso de contracts no desenvolvimento Android com Kotlin oferece uma maneira poderosa de definir e verificar condições críticas em seu código. Eles melhoram a segurança em tempo de compilação, tornam o código mais claro e reduzem a probabilidade de erros em tempo de execução. Implementar contracts em funções críticas pode aumentar significativamente a robustez e a qualidade geral do seu aplicativo. Como esse recurso ainda está em fase experimental, é importante acompanhar as atualizações da linguagem Kotlin para aproveitar ao máximo as melhorias e novidades futuras.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>android</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>O que há de novo no Android 13?</title>
      <dc:creator>Danilo Barreto</dc:creator>
      <pubDate>Sat, 04 Jun 2022 13:48:55 +0000</pubDate>
      <link>https://dev.to/dgbarreto/o-que-ha-de-novo-no-android-13-l68</link>
      <guid>https://dev.to/dgbarreto/o-que-ha-de-novo-no-android-13-l68</guid>
      <description>&lt;p&gt;Chegou aquela hora feliz do ano em que temos uma versão nova do Android. Anunciado no Google I/O, o Android 13 tem uma séries de melhorias e mudanças que afeta não só a vida do usuário final, como a vida de nós desenvolvedores. Eu separei algumas das mudanças que afetam mais a vida do desenvolvedor até agora:&lt;/p&gt;

&lt;p&gt;Primeiro e principalmente, quando deve sair:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8w5o72sbj8bb90ajmidv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8w5o72sbj8bb90ajmidv.png" alt=" " width="789" height="180"&gt;&lt;/a&gt;&lt;br&gt;
Já podemos baixar e começar a adaptar os nossos recursos, para o release em Julho!&lt;/p&gt;

&lt;p&gt;E o que mais?&lt;/p&gt;

&lt;p&gt;1) JetPack Compose 1.2: O JetPack Compose traz uma série de ferramentas para ajudar a montar interfaces mais ricas e fluídas de forma mais simples. Ele traz nessa nova versão recursos como Downloadable Fonts, onde o sistema busca e baixa diretamente fontes do Google Fonts, ajudando a diminuir o tamanho final do apk. Outro recurso interessantes é o Lazy Grid, permitindo montar grids de objetos em tamanho diferentes e não padronizados com menos linhas de código.&lt;/p&gt;

&lt;p&gt;2) Melhorias no Android Studio: com o lançamento do AS Dolphin e o Eletric Eel em Canary, temos um monte de recursos novos chegando.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LogCatV2: LogCat remodelado, ajudando na visualização, busca e filtro de registros&lt;/li&gt;
&lt;li&gt;Gradle Managed Devices: tudo o que você precisa fazer é descrever o device que precisa pra rodar os seus testes e o GMD cuida do resto pra você! Ele baixa o SDK, provisiona, executa os testes, desmonta o ambiente. &lt;/li&gt;
&lt;li&gt;Live Edit: todo o código que você altera, visualmente no Compose, pode ser visto em tempo real, não só na tela de preview como também no emulador e no device físico!&lt;/li&gt;
&lt;li&gt;Baseline Profiles: ele permite que apps e bibliotecas adicionem metadados em vistas a ajudar o compilador ahead-of-time a priorizar certos caminhos de código em vistas a deixar a experiência inicial do usuário mais rápida. Essa técnica já está sendo usada em libs como Fragments e Compose e também no app da Play Store, que já reportou ganho de velocidade de 40%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;3) Outras melhorias gerais como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Privacy Sandbox: um novo conjunto de APIs, ainda em preview, para disponibilização de conteúdo para o usuário de forma mais fácil e sem conflitar com as suas preferências de privacidade&lt;/li&gt;
&lt;li&gt;Google Wallet: o Google Pay Passes está integrando ao serviço de pagamentos agora chamado Google Wallet. A nova API agora permite a gravação de passes genéricos e o agrupamento em vouchers&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>android</category>
      <category>jetpack</category>
      <category>mobiledevelopment</category>
    </item>
    <item>
      <title>Opcionais no Swift</title>
      <dc:creator>Danilo Barreto</dc:creator>
      <pubDate>Fri, 17 Dec 2021 17:54:43 +0000</pubDate>
      <link>https://dev.to/dgbarreto/opcionais-no-swift-1c0o</link>
      <guid>https://dev.to/dgbarreto/opcionais-no-swift-1c0o</guid>
      <description>&lt;p&gt;Você já viu um monte de códigos no Swift com "?" e "!" e fica perdido? Usa esses operadores mas sem saber direito quando e onde usar? Esse post então é pra você. &lt;/p&gt;

&lt;h2&gt;
  
  
  O que é um "?" no Swift
&lt;/h2&gt;

&lt;p&gt;O símbolo "?" representa um opcional no Swift. E um opcional é (pasmem) um &lt;strong&gt;enum&lt;/strong&gt;: .Some(Valor Encapsulado) e .None. Isso permite que ele possa ser vazio (.None) ou possa ter algum valor internamente (.Some(valor).&lt;/p&gt;

&lt;p&gt;Exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ao criar uma variável com "?", no caso &lt;strong&gt;Int?&lt;/strong&gt; o Swift cria um enum do tipo &lt;strong&gt;Optional&lt;/strong&gt; mas com o estado &lt;strong&gt;.Some(10)&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caso contrário, se você atribui &lt;em&gt;nil&lt;/em&gt;, é criada uma variável do tipo &lt;strong&gt;Optional&lt;/strong&gt; com o estado &lt;strong&gt;.None&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparação
&lt;/h2&gt;

&lt;p&gt;Sabendo agora como é armazenado um &lt;em&gt;Opcional&lt;/em&gt;, o Swift oferece algumas formas de trabalhar com ele. Podemos comparar ele de algumas formas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;

&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Valor de x &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;None&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"x não tem valor"&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;Uma boa prática é "desembrulhar" (do inglês unwrap) o valor da váriavel de forma segura usando o guard. O guard pode ser executado da seguinte forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;?){&lt;/span&gt;
   &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&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;h2&gt;
  
  
  Encadeamento Opcional
&lt;/h2&gt;

&lt;p&gt;O encadeamento opcional permite você pegar o valor de dentro de um opcional. Diferente do Unwrapping Forçado que vou falar a seguir, ele não causa um erro caso não tenha um valor dento do Opcional. Vamos ao exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="c1"&gt;// .Some(10)&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="c1"&gt;// 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No exemplo simples acima quando eu chamo &lt;strong&gt;x?&lt;/strong&gt; eu faço um unwrapping do Opcional, ou seja, eu pego somente o valor que existe dentro dele. Vamos para um exemplo um pouco mais complexo. Considere o código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;residence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Residence&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Residence&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;numberOfRooms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora considere a seguinte função:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
   &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;john&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;roomCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;john&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;residence&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;numberOfRooms&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Número de quartos &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;roomCount&lt;/span&gt;&lt;span class="se"&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="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Não foi possível determinar o número de quartos"&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;O trecho de código acima não irá produzir um erro, pois o encadeamento opcional sempre retornar um Opcional que pode ser comparado. Mas ele será &lt;em&gt;nil&lt;/em&gt;. Então sua condição irá cair no &lt;em&gt;else&lt;/em&gt;. Mas se mudarmos aqui:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
   &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;john&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="n"&gt;john&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;residence&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Residence&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;roomCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;john&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;residence&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;numberOfRooms&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Número de quartos &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;roomCount&lt;/span&gt;&lt;span class="se"&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="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Não foi possível determinar o número de quartos"&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;O retorno será &lt;strong&gt;1&lt;/strong&gt;, pois é o valor padrão da quantidade de quartos. &lt;/p&gt;

&lt;h2&gt;
  
  
  Unwrapping Forçado
&lt;/h2&gt;

&lt;p&gt;O unwrapping forçado tem uma sintaxe parecida, trocando apenas "?" por "!". Mas ele tem uma diferença fundamental: Caso o valor no Opcional seja &lt;em&gt;nil&lt;/em&gt;, é gera um erro de execução e o aplicativo irá encerrar, caso não tratado. Utilizando o exemplo acima:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
   &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;john&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;roomCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;john&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;residence&lt;/span&gt;&lt;span class="o"&gt;!.&lt;/span&gt;&lt;span class="n"&gt;numberOfRooms&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;//o app irá quebrar nessa linha&lt;/span&gt;
      &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Número de quartos &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;roomCount&lt;/span&gt;&lt;span class="se"&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="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Não foi possível determinar o número de quartos"&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;o unwrapping forçado só deve ser usado caso você tenha ABSOLUTA CERTEZA de que o Opcional tenha valor. &lt;/p&gt;

&lt;h2&gt;
  
  
  Coalescência
&lt;/h2&gt;

&lt;p&gt;O operador de coalescência "??" permite que você retorne o primeiro valor não nulo (nil) de duas variáveis. Vamos deixar mais claro no exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="c1"&gt;//o valor de e será 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No exemplo acima prevalece o primeiro valor não nil. Segundo exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="c1"&gt;//o valor de e será 5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como no exemplo acima c é nil, o valor de e será 5, o primeiro valor não nil.&lt;/p&gt;

&lt;h2&gt;
  
  
  BONUS ADVANCED: Map e FlatMap
&lt;/h2&gt;

&lt;p&gt;O tipo Opcional ainda oferece duas funções chamadas Map e Flatmap que permitem que você controle o método de unwrapping passando um closure. A única diferença entro o Map e Flatmap é que o Map não pode devolver nil. Exemplos, exemplos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$0&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;z&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;FlatMap&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$0&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;É isso gente. Esse é todo o "mistério" dos Opcionais no Swift. A partir de agora você já sabe ler quando encontrar "?" e "!" nos códigos e sabe como posicionar nos seus próprios códigos.&lt;/p&gt;

&lt;p&gt;Até a próxima! Keep coding!&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Nativo x Hibrido?</title>
      <dc:creator>Danilo Barreto</dc:creator>
      <pubDate>Sat, 27 Nov 2021 20:42:20 +0000</pubDate>
      <link>https://dev.to/dgbarreto/nativo-x-hibrido-13g6</link>
      <guid>https://dev.to/dgbarreto/nativo-x-hibrido-13g6</guid>
      <description>&lt;p&gt;No desenvolvimento mobile nos dias de hoje temos diversas opções para criar um app. As pessoas me procuram sempre com essa dúvida: o que usar? E eu sempre respondo: depende!&lt;/p&gt;

&lt;p&gt;Não existe uma fórmula mágica que determine qual estratégia usar, mas eu reunião neste paper os principais pontos para essa tomada de decisão. A principal tomada de decisão, na minha visão, é se devemos seguir com o desenvolvimento nativo ou híbrido.&lt;/p&gt;

&lt;p&gt;Dentro do desenvolvimento híbrido, é claro, temos muitas vertentes, mas estou considerando por hora Flutter e React Native. Mas a decisão crucial ainda repousa entre o nativo x híbrido. As variações de equipe, custo, qualidade são enormes! &lt;/p&gt;

&lt;p&gt;Pode baixar o paper &lt;a href="https://1drv.ms/b/s!AhUytFEWx6jHg5YSVTqMFSD-TthOlA?e=Oj7QXH" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>nativo</category>
      <category>hibrido</category>
    </item>
    <item>
      <title>Injeção de Dependência</title>
      <dc:creator>Danilo Barreto</dc:creator>
      <pubDate>Tue, 16 Nov 2021 16:48:41 +0000</pubDate>
      <link>https://dev.to/dgbarreto/injecao-de-dependencia-5ap7</link>
      <guid>https://dev.to/dgbarreto/injecao-de-dependencia-5ap7</guid>
      <description>&lt;p&gt;O que é injeção de dependência? O que ela tem a ver comigo? O que ela come?&lt;/p&gt;

&lt;p&gt;A injeção de dependência é uma prática essencial nos dias de hoje. Apesar de eu falar sobre ela no âmbito do Android, ela é utilizada em todas as linguagens orientadas a objeto, pois ela fornece um fraco acoplamento entre as entidades, permitindo que a sua aplicação possua uma boa arquitetura. Ela também possui um papel fundamental nos testes automatizados, pois permite quer façamos a troca das dependências sem realizar nenhuma modificação nas classes.&lt;/p&gt;

&lt;h1&gt;
  
  
  Vamos de exemplo
&lt;/h1&gt;

&lt;p&gt;Imagine um carro. O carro possui uma dependência de um motor. Nós podemos representar dessa forma no Kotlin:&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;engine&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&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;Nesse caso o motor está definido dentro do carro. Temos um acoplamento forte, pois o carro só permite um tipo de motor. Essa relação cria uma dificuldade caso eu queira um motor diferente. Nos testes automatizados, caso eu queira criar um FakeMotor() isso também não seria possível. &lt;br&gt;
Mas com uma alteração já podemos ver algo diferente:&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&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;Aqui já podemos dizer que temos uma injeção de dependência! Quando recebemos o Engine como parâmetro permitimos diferentes implementações como um EletricMotor ou um FakeMotor no caso de um teste automático. A forma demostrada acima é chamada de &lt;strong&gt;Injeção de Construtor&lt;/strong&gt;. No Android podemos fazer de outra forma com Kotlin:&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="kd"&gt;class&lt;/span&gt; &lt;span class="err"&gt;car {

   lateinit var engine: &lt;/span&gt;&lt;span class="nc"&gt;Engine&lt;/span&gt;

   &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&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="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;car&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&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;Essa segunda forma é chamada se &lt;strong&gt;Injeção de Setter&lt;/strong&gt;. Como Algumas classes são instanciadas por sistema, como Activities ou Fragments, as vezes não é possível se utilizar da Injeção por Construtor.&lt;/p&gt;

&lt;p&gt;Essa é a forma manual de injeção de dependência. Agora imagine que você precisa instanciar todas a partes de um carro? Muita coisa né? Pra isso existem bibliotecas como o Dagger ou o Hilt que podem ajudar a fazer isso de forma automática criando um Graph em memória. Mas isso é assunto para um próximo artigo. A lição valiosa importante aqui é gerar um acoplamento forte da sua classe, pois isso engessa o seu modelo e torna qualquer teste e qualquer refatoração um trabalhão no futuro!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Nova ferramenta do Facebook para encontrar falhas de segurança em apps Android</title>
      <dc:creator>Danilo Barreto</dc:creator>
      <pubDate>Fri, 08 Oct 2021 20:43:00 +0000</pubDate>
      <link>https://dev.to/dgbarreto/nova-ferramenta-do-facebook-para-encontrar-falhas-de-seguranca-em-apps-android-4kia</link>
      <guid>https://dev.to/dgbarreto/nova-ferramenta-do-facebook-para-encontrar-falhas-de-seguranca-em-apps-android-4kia</guid>
      <description>&lt;p&gt;Há alguns dias o Facebook liberou para o público uma ferramenta, até então caseira, para descobrir falhas de segurança e privacidade em aplicações Anndroid e Java. &lt;/p&gt;

&lt;p&gt;Batizada de Mariana Trench (MT) e distribuida de forma Open Source a ferramenta está em constante evolução e suporte pelo time de engenharia do Facebook. Ela é usada hoje em milhões de linhas de código no Whatsapp, Instagram e, claro, no próprio app do Facebook. Segundo o Facebook, na primeira metade de 2021, 50% das vulnerabilidades encontradas foram de forma automatizada.&lt;/p&gt;

&lt;p&gt;O MT foi desenvolvido em Python e roda de forma estática no código. Está disponível (aqui)[&lt;a href="https://github.com/facebook/mariana-trench/" rel="noopener noreferrer"&gt;https://github.com/facebook/mariana-trench/&lt;/a&gt;). O Facebook também deixou pronto um tutorial para facilitar nos primeiros passos. O tutorial pode ser acessado (aqui)[&lt;a href="https://mariana-tren.ch/docs/getting-started/" rel="noopener noreferrer"&gt;https://mariana-tren.ch/docs/getting-started/&lt;/a&gt;].&lt;/p&gt;

</description>
      <category>android</category>
      <category>facebook</category>
      <category>security</category>
    </item>
    <item>
      <title>Face Detection com Android e Kotlin</title>
      <dc:creator>Danilo Barreto</dc:creator>
      <pubDate>Thu, 23 Sep 2021 18:37:10 +0000</pubDate>
      <link>https://dev.to/dgbarreto/face-detection-com-android-e-kotlin-3i86</link>
      <guid>https://dev.to/dgbarreto/face-detection-com-android-e-kotlin-3i86</guid>
      <description>&lt;p&gt;O Google disponibiliza uma API que permite realizar detecção de rostos de maneira offline, sem depender de nenhum serviço na nuvem. Essa API é a Google Vision e foi introduzida no Play Services na versão 8.1. Fazer uma implementação básica é bem simples:&lt;/p&gt;

&lt;p&gt;Inclua a referência no build.gradle:&lt;br&gt;
&lt;code&gt;implementation 'com.google.android.gms:play-services-vision:8.1.0'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Em seguida vem a implementação do controle&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="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.avanade.myfacedetection&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.content.Context&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.graphics.*&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.util.AttributeSet&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.util.SparseArray&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.view.View&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;androidx.core.util.valueIterator&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.google.android.gms.vision.Frame&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.google.android.gms.vision.face.Face&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.google.android.gms.vision.face.FaceDetector&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FaceOverlayView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AttributeSet&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;defStyleAttr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;View&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;defStyleAttr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AttributeSet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;lateinit&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;mBitmap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Bitmap&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;mFaces&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;SparseArray&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Face&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SparseArray&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Face&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;setBitmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bitmap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Bitmap&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="n"&gt;mBitmap&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bitmap&lt;/span&gt;

        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;faceDetector&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;FaceDetector&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FaceDetector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setTrackingEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setLandmarkType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;FaceDetector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ALL_LANDMARKS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;FaceDetector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ACCURATE_MODE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;faceDetector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isOperational&lt;/span&gt;&lt;span class="p"&gt;()){&lt;/span&gt;
            &lt;span class="c1"&gt;//TODO: Colocar verificação&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;frame&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Frame&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Frame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setBitmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mBitmap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;mFaces&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;faceDetector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;detect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;faceDetector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;release&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nf"&gt;invalidate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onDraw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Canvas&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onDraw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mBitmap&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;mFaces&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&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;scale&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;drawBitmap&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="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;canvas&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
                &lt;span class="nf"&gt;drawFaceBox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scale&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;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;drawBitmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Canvas&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;viewWidth&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;viewHeight&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;imageWidth&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mBitmap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;imageHeight&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mBitmap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;scale&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viewWidth&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="n"&gt;imageWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;viewHeight&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="n"&gt;imageHeight&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;bounds&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Rect&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Rect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;imageWidth&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;imageHeight&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawBitmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mBitmap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bounds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;drawFaceBox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&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;paint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Paint&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Paint&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;BLUE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Paint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;STROKE&lt;/span&gt;
        &lt;span class="n"&gt;paint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strokeWidth&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;5F&lt;/span&gt;

        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;left&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Float&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0F&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;top&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Float&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0F&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;right&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Float&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0F&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;bottom&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Float&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0F&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;face&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;mFaces&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;valueIterator&lt;/span&gt;&lt;span class="p"&gt;()){&lt;/span&gt;
            &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;face&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;
            &lt;span class="n"&gt;top&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;face&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;
            &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;face&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;face&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;bottom&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;face&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;face&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawRect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;paint&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;Aqui fazemos a criação do objeto que faz a detecção dos rostos na foto&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="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;faceDetector&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;FaceDetector&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FaceDetector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setTrackingEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setLandmarkType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;FaceDetector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ALL_LANDMARKS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;FaceDetector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ACCURATE_MODE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Logo abaixo temos &lt;code&gt;if(!faceDetector.isOperational())&lt;/code&gt; que é uma verificação importante. Caso o usuário nunca tenha usado em nenhuma aplicação a API do Google Vision o device vai baixar essa lib e, pode ser que nesse momento a API ainda não esteja disponível. Então é importante fazer essa verificação para evitar um erro de NullPointerException.&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="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;frame&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Frame&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Frame&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setBitmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mBitmap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;mFaces&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;faceDetector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;detect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;faceDetector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;release&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui é onde o código irá efetivamente analisar a imagem e verificar os rostos das pessoas. As informações dos rostos encontrados é armazenado em um array de Faces usado aqui para desenhar os quadrados sobre o frame:&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="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;face&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;mFaces&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;valueIterator&lt;/span&gt;&lt;span class="p"&gt;()){&lt;/span&gt;
            &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;face&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;
            &lt;span class="n"&gt;top&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;face&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;
            &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;face&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;face&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;bottom&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;face&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;face&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawRect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;paint&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;O código completo está aqui no &lt;a href="https://github.com/dgbarreto/facedetectionandroidkotlin" rel="noopener noreferrer"&gt;repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Aqui também está um vídeo da implementação:&lt;br&gt;
&lt;a href="http://www.youtube.com/watch?feature=player_embedded&amp;amp;v=YlA1X6zcw_8" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fimg.youtube.com%2Fvi%2FYlA1X6zcw_8%2F0.jpg" alt="Face Detection com Android e Kotlin" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>android</category>
      <category>kotlin</category>
      <category>androidstudio</category>
      <category>facedetection</category>
    </item>
    <item>
      <title>Mudança de Privacidade Chegando</title>
      <dc:creator>Danilo Barreto</dc:creator>
      <pubDate>Wed, 22 Sep 2021 12:41:52 +0000</pubDate>
      <link>https://dev.to/dgbarreto/mudanca-de-privacidade-chegando-k0g</link>
      <guid>https://dev.to/dgbarreto/mudanca-de-privacidade-chegando-k0g</guid>
      <description>&lt;p&gt;O Google estará liberando nos próximos meses uma melhoria nos recursos de privacidade. Esse recurso terá como algo todas aquelas aplicações mais antigas, esquecidas e sem uso, que possuam acesso a dados sensíveis.&lt;br&gt;
Entre os recursos que serão "perdidos" para essas apps estão envio de SMS, sensores e acesso à lista de contatos.&lt;br&gt;
"O recurso será habilitade por padrão em apps rodando Android 11 (API level 30) ou superior. Contudo, usuários poderão habilitar auto-reset de permissões para apps rodando com API levels 23 a 29", disse o Google.&lt;/p&gt;

&lt;p&gt;Esse novo recurso visa aumentar ainda mais a segurança digital, prevenindo que apps antigas possam se aproveitar desses acessos concedidos e, com alguma atualização, rodar algum código malicioso ou abrir portas para tal. &lt;/p&gt;

&lt;p&gt;A atualização deve começar a sair para o público geral a partir de Dezembro, mas deve demorar até o final de Março/2022 para atingir todo o público esperado.&lt;/p&gt;

</description>
      <category>android</category>
      <category>security</category>
      <category>news</category>
    </item>
    <item>
      <title>Android ViewModel</title>
      <dc:creator>Danilo Barreto</dc:creator>
      <pubDate>Sat, 18 Sep 2021 14:54:17 +0000</pubDate>
      <link>https://dev.to/dgbarreto/android-viewmodel-11c3</link>
      <guid>https://dev.to/dgbarreto/android-viewmodel-11c3</guid>
      <description>&lt;p&gt;Uma das práticas básicas de desenvolvimento que temos que adotar assim que saímos do campo de estudos e entramos no campo de desenvolvimento profissional de aplicativos é separar a camada de negócios da camada de visualização. A camada de visualização possui um ciclo de vida próprio que muda de acordo com o estado do device (se a app está em primeiro ou segundo plano, se rotacionamos o aparelho, se o SO solicita memória, etc). Os dados de negócio não podem estar sujeitos a esses tipos de mudança. &lt;br&gt;
Para auxiliar essa implementação o Kotlin traz o ViewModel. O ViewModel permite realizar uma delegação e uma separação dos dados de negócio. Vamos à implantação:&lt;/p&gt;

&lt;p&gt;O primeiro passo é a referencia à biblioteca no build.gradle.&lt;br&gt;
&lt;code&gt;implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A seguir no projeto crie uma classe herdando de ViewModel&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="k"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PackageModel&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ViewModel&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;Agora vem a parte importante da implementação. O Kotlin possui um recurso chamado &lt;strong&gt;Property Delegate&lt;/strong&gt;. Basicamente ele permite que uma propriedade delegue o &lt;strong&gt;getter&lt;/strong&gt; e o &lt;strong&gt;setter&lt;/strong&gt; para uma classe externa. A sintaxe é essa:&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="kd"&gt;var&lt;/span&gt; &lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="py"&gt;nome&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="n"&gt;tipo&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;classe&lt;/span&gt; &lt;span class="n"&gt;delegada&lt;/span&gt;&lt;span class="p"&gt;]()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No nosso caso, vamos declarar a propriedade delegada do modelo dentro de uma Activity ou Fragment. Vai ficar assim:&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="k"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;model&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;PackageModel&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nf"&gt;viewModels&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No exemplo acima &lt;strong&gt;viewModels()&lt;/strong&gt; é um property delegate que vem pronto do Kotlin.&lt;/p&gt;

&lt;p&gt;Deste ponto em diante basta implementar as propriedades e métodos necessários &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Flutter 2.5 - O que há de novo?</title>
      <dc:creator>Danilo Barreto</dc:creator>
      <pubDate>Sat, 11 Sep 2021 00:19:54 +0000</pubDate>
      <link>https://dev.to/dgbarreto/flutter-2-5-o-que-ha-de-novo-540p</link>
      <guid>https://dev.to/dgbarreto/flutter-2-5-o-que-ha-de-novo-540p</guid>
      <description>&lt;p&gt;Esse release foi realmente bem grande! Alguns números:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;4600 issues encerradas&lt;/li&gt;
&lt;li&gt;3932 PRs fechadas&lt;/li&gt;
&lt;li&gt;252 contribuidores&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(fonte &lt;a href="https://medium.com/flutter/whats-new-in-flutter-2-5-6f080c3f3dc" rel="noopener noreferrer"&gt;flutter.dev&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Vamos ver algumas melhorias&lt;/p&gt;

&lt;h1&gt;
  
  
  Framework
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Android Full Screen
&lt;/h2&gt;

&lt;p&gt;Agora o Flutter oferece suporte à tela cheia no Android. Suporta os seguintes modos: Lean back, Immersive, Immersive Stick e Edge-to-Edge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Material You
&lt;/h2&gt;

&lt;p&gt;Suporte à nova versão do Android Material Design. Em breve vou liberar um novo artigo com as novidades!&lt;/p&gt;

&lt;h2&gt;
  
  
  Visual Studio Code
&lt;/h2&gt;

&lt;p&gt;Update no plugin do Visual Studio Code inclui dois novos comandos para facilitar a instalação de dependências e dependências de desenvolvimento do Dart. Além disso tem um novo test runner ainda em preview, mas que logo deve substituir o atual.&lt;/p&gt;

&lt;h1&gt;
  
  
  Dart 2.14
&lt;/h1&gt;

&lt;p&gt;Com a atualização do Flutter também chega uma atualização do Dart. Algumas mudanças são:&lt;/p&gt;

&lt;h2&gt;
  
  
  Lint
&lt;/h2&gt;

&lt;p&gt;Agora ao criar o projeto já é criado um set de lints padrão, o que não era possível antes. Agora a análise com Lint ficou bem mais fácil e intuitiva.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nova formatação
&lt;/h2&gt;

&lt;p&gt;Vem com um novo padrão de formatação para permitir que o cascateamento de comandos fique mais claro. Só tenho a agradecer por esse item :)&lt;/p&gt;

&lt;p&gt;Essas são as melhorias principais e as mais visíveis. Além delas houveram várias correções de bugs e melhorias de performance. Os detalhes podem ser visto no artigo oficial do &lt;a href="https://medium.com/flutter/whats-new-in-flutter-2-5-6f080c3f3dc" rel="noopener noreferrer"&gt;flutter.dev&lt;/a&gt;.&lt;/p&gt;

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

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>materialyou</category>
    </item>
  </channel>
</rss>
