<?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: Wesley Oliveira</title>
    <description>The latest articles on DEV Community by Wesley Oliveira (@wesleybruno).</description>
    <link>https://dev.to/wesleybruno</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F557835%2F6a3a6a04-7b53-4ddd-928c-c6c7b3751f7f.jpeg</url>
      <title>DEV Community: Wesley Oliveira</title>
      <link>https://dev.to/wesleybruno</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wesleybruno"/>
    <language>en</language>
    <item>
      <title>Flutter  - Builder Pattern - Gerando textos estilizados</title>
      <dc:creator>Wesley Oliveira</dc:creator>
      <pubDate>Thu, 11 Feb 2021 15:10:52 +0000</pubDate>
      <link>https://dev.to/wesleybruno/flutter-builder-pattern-gerando-textos-estilizados-5bkl</link>
      <guid>https://dev.to/wesleybruno/flutter-builder-pattern-gerando-textos-estilizados-5bkl</guid>
      <description>&lt;p&gt;Recentemente comecei a estudar um pouco de Swift/IOS para poder &lt;em&gt;"sair do 0"&lt;/em&gt;, saber como funciona as coisas nesse mundo até então desconhecido para mim.&lt;/p&gt;

&lt;p&gt;Resolvi fazer um curso básico no site, &lt;a href="https://www.raywenderlich.com"&gt;Raywenderlich&lt;/a&gt; , que por sinal um excelente curso.&lt;/p&gt;

&lt;p&gt;Logo no começo do curso achei diferente a forma como são gerados os componentes visuais, diferente das widgets do flutter lá tudo são views.&lt;/p&gt;

&lt;p&gt;A forma como são geradas essas views lembram bastante o design pattern builder ¹, como pode ser visto abaixo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xJ4zPrLB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3utwyoplacblc7mbo2y8.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xJ4zPrLB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3utwyoplacblc7mbo2y8.PNG" alt="IOS Text View"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;¹ Caso não tenha conhecimento sobre esse padrão sugiro assistir esse vídeo &lt;a href="https://www.youtube.com/watch?v=x5u9VOdnZ3Q&amp;amp;t=764s"&gt;Builder Pattern&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Transformando a view acima para flutter teriamos algo semelhante a isto:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dfbom9OG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h9p3j9roiili6czyckup.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dfbom9OG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h9p3j9roiili6czyckup.png" alt="Flutter Text Widget"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como pode ser visto tem uma grande diferença na forma como são criados.&lt;/p&gt;

&lt;p&gt;A partir desse ponto, irei focar apenas no flutter.&lt;/p&gt;

&lt;h2&gt;
  
  
  O Problema
&lt;/h2&gt;

&lt;p&gt;Imagine uma situação onde em uma mesma linha deva ter diversos estilos textuais aplicados, por exemplo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Texto em negrito&lt;/strong&gt;, &lt;em&gt;texto em italico&lt;/em&gt;, texto normal.&lt;/p&gt;

&lt;p&gt;Flutter tem o poder de transformar isso em tarefa bem simples, aplicando apenas uma Text com alguns TextSpan isso se torna uma tarefa fácil como está na imagem abaixo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZiN3N3OI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7gqjb98ocb7m86civs8n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZiN3N3OI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7gqjb98ocb7m86civs8n.png" alt="Flutter text widget 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E se forem mais estilos, 10, 20, claro que isso é um cenário difícil de acontecer, mas caso aconteça, o quanto esse widget iria crescer?&lt;/p&gt;

&lt;h2&gt;
  
  
  Solução proposta
&lt;/h2&gt;

&lt;p&gt;Pensando nesse improvável panorama, lembrei da implementação do IOS e com o pattern Builder, pensei em tentar adaptar para o flutter.&lt;/p&gt;

&lt;p&gt;Depois de algum tempo estudando, cheguei a esse pequeno esboço.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/wesleybruno/flutter_gerador_textos_estilizados"&gt;Flutter Gerador Textos Estilizados&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A implementação foi feita seguindo o Builder pattern, e para utiliza-lo ficou bastante simples.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sfwpnYLC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/s2vgc82qf2q9h9l1lb2c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sfwpnYLC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/s2vgc82qf2q9h9l1lb2c.png" alt="Gerador Textos Widget"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como tudo no mundo da programação, não existe uma bala de prata! Existem N cenários e cada um deve ser avaliado a melhor opção, além de que isso é apenas uma ideia de algo pode ou não ser útil para alguém, mas afim de compartilhar um aprendizado resolvi escrever esse post.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Flutter Image File Upload - Base64 x MultiPart Form</title>
      <dc:creator>Wesley Oliveira</dc:creator>
      <pubDate>Mon, 11 Jan 2021 14:34:34 +0000</pubDate>
      <link>https://dev.to/wesleybruno/flutter-file-upload-base64-x-multipart-form-2a2d</link>
      <guid>https://dev.to/wesleybruno/flutter-file-upload-base64-x-multipart-form-2a2d</guid>
      <description>&lt;p&gt;Recentemente comecei a pesquisar diferentes temas que poderiam ser utilizados para escrever algum conteúdo, foi aí que um amigo escreveu o primeiro artigo e utilizou de um problema que aconteceu em seu dia a dia para transformá-lo em uma ideia de artigo, para escrever esse pequeno artigo resolvi tentar da mesma maneira.&lt;/p&gt;

&lt;p&gt;Passamos por uns erros no quesito de upload de uma imagem para a api via Base64, resolvi então mostrar aqui alguns problemas dessa abordagem e uma alternativa para a mesma.&lt;/p&gt;

&lt;p&gt;Base64 é um método para codificação de dados para transferência na Internet. É utilizado frequentemente para transmitir dados binários por meios de transmissão que lidam apenas com texto, como por exemplo para enviar arquivos anexos por e-mail.&lt;/p&gt;

&lt;p&gt;Para converter um arquivo para Base64 no flutter é muito simples vide código baixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;File&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ImagePicker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pickImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ImageSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="nx"&gt;base64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;base64Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readAsBytesSync&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;¹ ImagePicker - Plugin Flutter para iOS e Android para selecionar imagens da galeria ou tirar uma nova foto com a câmera. &lt;a href="https://pub.dev/packages/image_picker" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Obtido o Base64, o mesmo pode ser enviado no &lt;em&gt;body&lt;/em&gt; de uma requisição &lt;em&gt;post&lt;/em&gt; por exemplo.&lt;/p&gt;

&lt;h1&gt;
  
  
  Problemas com Base64
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Respostas de API ficam muito grandes
&lt;/h3&gt;

&lt;p&gt;Respostas muito grandes tendem a levar mais tempo para serem processadas dando mais tempo para uma possível falha na rede e aumentando o consumo de dados do dispositivo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Oversizing
&lt;/h3&gt;

&lt;p&gt;O tamanho da imagem codificada em Base64 é aproximadamente 30% maior do que a imagem binária original.&lt;/p&gt;

&lt;h3&gt;
  
  
  A experiência do usuário é afetada negativamente.
&lt;/h3&gt;

&lt;p&gt;Incluindo os retornos junto com outras respostas da API, o aplicativo irá esperar carregar todos os dados antes de exibir informações na tela, afetando assim a experiência do usuário que verá uma tela de carregamento por mais tempo.&lt;/p&gt;

&lt;h3&gt;
  
  
  O armazenamento em cache de imagens no dispositivo não é mais possível.
&lt;/h3&gt;

&lt;p&gt;Imagens enviadas para o dispositivo via Base64 tornará irrelevante qualquer implementação de serviços de cache de armazenamento de imagens.&lt;/p&gt;

&lt;p&gt;Recursos nativos do flutter como o precacheImage tornam-se inutilizáveis nesta situação, já que toda vez será necessário fazer o decode do base64.&lt;/p&gt;

&lt;p&gt;Outra implementação que se torna inutilizável seria o cachedNetworkImage, outra implementação nativa do flutter, mas que não pode ser  aplicada ao contexto de um Base64.&lt;/p&gt;

&lt;p&gt;Para aplicativos que possam funcionar tanto online quanto offline, a utilização de cache de imagens é um recurso bem eficaz para melhor experiência do usuário.&lt;/p&gt;

&lt;h1&gt;
  
  
  Vantagens do Base64
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Remover a necessidade de múltiplos request, para obtenção de dados. ²&lt;/li&gt;
&lt;li&gt;Imagens codificadas como Base64 podem ser armazenadas em bancos de dados e gerados novos arquivos.
² Como foi mostrado antes, essa abordagem pode ser uma vantagem ou uma desvantagem a depender do contexto e da implementação&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Multipart Form Data
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;É uma de três formas de codificação existentes no HTML sendo elas: &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;1.application/x-www-form-urlencoded &lt;br&gt;
2.multipart/form-data&lt;br&gt;
3.text/plain&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deve-se utilizar esta forma de codificação quando a requisição possuir algum arquivo que deve fazer upload &lt;/li&gt;
&lt;li&gt;É compatível com todos os navegadores.&lt;/li&gt;
&lt;li&gt;Suporta arquivos com tamanhos muito grandes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Utilizando multipart com Flutter
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;File&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ImagePicker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pickImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ImageSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;final&lt;/span&gt; &lt;span class="nx"&gt;multiPartdata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;MultipartFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;final&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromMap&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
     &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;file&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;multiPartdata&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;Desta maneira o servidor da API deve estar preparado para receber requisições com o cabeçalho multipart/form-data, já que o conteúdo não irá junto com o body da requisição caso o mesmo exista.&lt;/p&gt;

&lt;p&gt;Alguns servidores de storage como &lt;strong&gt;&lt;em&gt;aws.s3&lt;/em&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;em&gt;cloudinary&lt;/em&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;em&gt;firebase cloud storage&lt;/em&gt;&lt;/strong&gt;, estão preparados para receberem requisições nesse formato, possuindo libs para integração direta em Flutter, dispensando a necessidade da criação de uma api própria.&lt;/p&gt;

&lt;h1&gt;
  
  
  Resolvendo o Oversizing
&lt;/h1&gt;

&lt;p&gt;Algumas estratégias podem ser admitidas a fim de reduzir o oversizing, a mais comum são os famosos thumbnails, algumas alternativas mais recentes que têm grande aplicabilidade a depender do contexto seriam o blurHash e a Dominant color  abaixo explico o funcionamento de ambas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Thumbnails
&lt;/h3&gt;

&lt;p&gt;Uma thumbnail é uma imagem comprimida que prevê a imagem original. Elas são mais leves e podem ser utilizadas para diversos fins. Por exemplo, um dos propósitos da utilização dessa thumb é reduzir o tempo de carregamento de alguma pagina na internet, para tornar o acesso mais rápido ao usuário. Então, uma thumbnail de uma foto maior, seria uma versão reduzida dela mesma.&lt;/p&gt;

&lt;p&gt;Em essência, a principal função de uma miniatura é trazer uma informação ao usuário de maneira mais rápida.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://github.com/woltapp/blurhash" rel="noopener noreferrer"&gt;Blurhash&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;“BlurHash is a compact representation of a placeholder for an image”.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Blurhash é uma representação compacta de um espaço reservado para uma imagem. Esta é a definição dada pelos desenvolvedores. Trata-se de uma biblioteca que converte uma imagem para uma versão ofuscada e compactada de sua versão.&lt;br&gt;
Essa biblioteca possui implementações para diversas linguagens, typescript, kotlin, swift, python, C, entre outras. Segue abaixo uma visão da mesma.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhjznmr681n753svu8qh7.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhjznmr681n753svu8qh7.JPG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Dominant color
&lt;/h3&gt;

&lt;p&gt;Trata-se apenas de pegar a cor de maior incidência na imagem, e utilizá-la no local da mesma. Estratégia bastante parecida com o blurHash, a diferença seria apenas o resultado final da imagem.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnylgnpitcxgk8wpqp1wb.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnylgnpitcxgk8wpqp1wb.JPG"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Referencial Bibliográfico
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://medium.com/snapp-mobile/dont-use-base64-encoded-images-on-mobile-13ddeac89d7c" rel="noopener noreferrer"&gt;https://medium.com/snapp-mobile/dont-use-base64-encoded-images-on-mobile-13ddeac89d7c&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pt.wikipedia.org/wiki/Base64" rel="noopener noreferrer"&gt;https://pt.wikipedia.org/wiki/Base64&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pub.dev/packages/image_picker" rel="noopener noreferrer"&gt;https://pub.dev/packages/image_picker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/snapp-mobile/dont-use-base64-encoded-images-on-mobile-13ddeac89d7c" rel="noopener noreferrer"&gt;https://medium.com/snapp-mobile/dont-use-base64-encoded-images-on-mobile-13ddeac89d7c&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.coderiddles.com/base64-images/" rel="noopener noreferrer"&gt;http://www.coderiddles.com/base64-images/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://neilpatel.com/br/blog/thumbnail-o-que-e/" rel="noopener noreferrer"&gt;https://neilpatel.com/br/blog/thumbnail-o-que-e/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/woltapp/blurhash" rel="noopener noreferrer"&gt;https://github.com/woltapp/blurhash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://lokeshdhakar.com/projects/color-thief/" rel="noopener noreferrer"&gt;https://lokeshdhakar.com/projects/color-thief/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://flutter.dev/docs/cookbook/images/cached-images" rel="noopener noreferrer"&gt;https://flutter.dev/docs/cookbook/images/cached-images&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
