<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Go Pato]]></title><description><![CDATA[Hi there, I am Patrick a software Engineer]]></description><link>https://blog.iampato.me</link><generator>RSS for Node</generator><lastBuildDate>Wed, 15 Apr 2026 07:49:03 GMT</lastBuildDate><atom:link href="https://blog.iampato.me/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Python Multiprocessing: A Finesse Approach]]></title><description><![CDATA[A declaration
This content is not AI-generated whatsoever, so help me God.

Introduction
It’s 2025, and the 18-year-old me would never think I would be writing a blog on Python. As a platform engineer, I find myself running migrations of databases. A...]]></description><link>https://blog.iampato.me/python-multiprocessing-a-finesse-approach</link><guid isPermaLink="true">https://blog.iampato.me/python-multiprocessing-a-finesse-approach</guid><category><![CDATA[Python]]></category><category><![CDATA[Platform Engineering ]]></category><category><![CDATA[10xengineer]]></category><dc:creator><![CDATA[Patrick Waweru]]></dc:creator><pubDate>Wed, 03 Dec 2025 08:20:11 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-a-declaration">A declaration</h2>
<p>This content is not AI-generated whatsoever, so help me God.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764090252715/db1cbf96-6956-47f7-95b7-6dcb890cf7a1.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-introduction">Introduction</h2>
<p>It’s 2025, and the 18-year-old me would never think I would be writing a blog on Python. As a platform engineer, I find myself running migrations of databases. As I advanced in these things, I found Python scripts are things I can depend on to get the job done, simulating migrations without hard writes, etc…</p>
<p>Today, we aren’t here to talk about migrations, but how I’m leveraging Python <code>multiprocessing</code> to run them quickly, and Multiprocessing is not concurrency but “true” Parallelism, aka doing multiple things at the same time.</p>
<h2 id="heading-a-back-story">A back story</h2>
<p>Say you are a painter, and you have 100 rooms to paint in an apartment, options:</p>
<ul>
<li><p><strong>Single Processing</strong> (traditional approach)</p>
<p>  You are one painter who has to paint room 1, finish goes to 2, and so on, till you reach room 100.</p>
<p>  The only Advantage is the memory space one painter takes up space based on the room. On the downside is time, say you take 30 mins per room, that would be 30 × 100 = <code>3000 mins</code> ~ 50 hours</p>
</li>
<li><p><strong>Multi Processing</strong></p>
<p>  Another approach, say you hire 10 painters, in this case, they represent processes, each painter takes up memory space (n), during execution, <code>painter 1</code> takes up rooms 1 to 10, <code>painter 2</code> takes up rooms 11 to 20, and so forth. With a bit of memory sacrifice, you will save time, 50 hours being cut into:<br />  10 rooms X 30 mins = <code>300 mins</code> ~ 5 hours. Which is way faster</p>
</li>
</ul>
<h2 id="heading-python-interpretation">Python Interpretation</h2>
<p>The above can be represented by the code snippet below</p>
<pre><code class="lang-python"><span class="hljs-comment"># This is like having one painter</span>
<span class="hljs-keyword">for</span> room <span class="hljs-keyword">in</span> rooms:
    paint_room(room)  <span class="hljs-comment"># Takes 30 minutes each</span>

<span class="hljs-comment"># This is like having multiple painters</span>
<span class="hljs-keyword">with</span> Pool(processes=<span class="hljs-number">10</span>) <span class="hljs-keyword">as</span> pool:
    pool.map(paint_room, rooms)  <span class="hljs-comment"># All painters work simultaneously</span>
</code></pre>
<h2 id="heading-limitations-to-multiprocessing">Limitations to Multiprocessing</h2>
<p>Based on my experience, it might be a bad thing for production usage <strong>depending</strong> on the use case.</p>
<ol>
<li><p><strong>Number of Cores</strong></p>
<p> There is no faking till you make it here. And I learnt the hard way after seeing very weird behaviours in database updates. <code>The more the workers never means faster execution</code> Here is a breakdown:</p>
<pre><code class="lang-python"> <span class="hljs-keyword">import</span> time
 <span class="hljs-keyword">from</span> multiprocessing <span class="hljs-keyword">import</span> Pool
 <span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt

 <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">cpu_intensive_task</span>(<span class="hljs-params">n</span>):</span>
     total = <span class="hljs-number">0</span>
     <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">10000000</span>):
         total += i * n
     <span class="hljs-keyword">return</span> total

 <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">benchmark_workers</span>(<span class="hljs-params">max_workers=<span class="hljs-number">32</span>, tasks=<span class="hljs-number">32</span></span>):</span>
     results = []

     <span class="hljs-keyword">for</span> num_workers <span class="hljs-keyword">in</span> range(<span class="hljs-number">1</span>, max_workers + <span class="hljs-number">1</span>):
         start = time.time()

         <span class="hljs-keyword">with</span> Pool(processes=num_workers) <span class="hljs-keyword">as</span> pool:
             pool.map(cpu_intensive_task, range(tasks))

         elapsed = time.time() - start
         results.append({
             <span class="hljs-string">'workers'</span>: num_workers,
             <span class="hljs-string">'time'</span>: elapsed,
             <span class="hljs-string">'tasks_per_second'</span>: tasks / elapsed
         })
         print(<span class="hljs-string">f"Workers: <span class="hljs-subst">{num_workers:<span class="hljs-number">3</span>d}</span> | Time: <span class="hljs-subst">{elapsed:<span class="hljs-number">.2</span>f}</span>s | Tasks/sec: <span class="hljs-subst">{tasks/elapsed:<span class="hljs-number">.2</span>f}</span>"</span>)

     <span class="hljs-keyword">return</span> results

 <span class="hljs-comment"># Run benchmark</span>
 results = benchmark_workers(max_workers=<span class="hljs-number">32</span>, tasks=<span class="hljs-number">32</span>)
 ```

 <span class="hljs-comment">### Typical Results Pattern (8-core machine):</span>
 ```
 Workers:   <span class="hljs-number">1</span> | Time: <span class="hljs-number">32.00</span>s | Tasks/sec: <span class="hljs-number">1.00</span>   ← Baseline
 Workers:   <span class="hljs-number">2</span> | Time: <span class="hljs-number">16.10</span>s | Tasks/sec: <span class="hljs-number">1.99</span>   ← ~<span class="hljs-number">2</span>x faster ✓
 Workers:   <span class="hljs-number">4</span> | Time:  <span class="hljs-number">8.20</span>s | Tasks/sec: <span class="hljs-number">3.90</span>   ← ~<span class="hljs-number">4</span>x faster ✓
 Workers:   <span class="hljs-number">6</span> | Time:  <span class="hljs-number">5.60</span>s | Tasks/sec: <span class="hljs-number">5.71</span>   ← ~<span class="hljs-number">6</span>x faster ✓
 Workers:   <span class="hljs-number">8</span> | Time:  <span class="hljs-number">4.10</span>s | Tasks/sec: <span class="hljs-number">7.80</span>   ← ~<span class="hljs-number">8</span>x faster ✓
 Workers:  <span class="hljs-number">10</span> | Time:  <span class="hljs-number">4.05</span>s | Tasks/sec: <span class="hljs-number">7.90</span>   ← Marginal improvement
 Workers:  <span class="hljs-number">12</span> | Time:  <span class="hljs-number">4.02</span>s | Tasks/sec: <span class="hljs-number">7.96</span>   ← Barely faster
 Workers:  <span class="hljs-number">16</span> | Time:  <span class="hljs-number">4.00</span>s | Tasks/sec: <span class="hljs-number">8.00</span>   ← Plateauing
 Workers:  <span class="hljs-number">20</span> | Time:  <span class="hljs-number">4.01</span>s | Tasks/sec: <span class="hljs-number">7.98</span>   ← No improvement
 Workers:  <span class="hljs-number">32</span> | Time:  <span class="hljs-number">4.15</span>s | Tasks/sec: <span class="hljs-number">7.71</span>   ← SLOWER! ✗
 ```

 <span class="hljs-comment">## Why This Happens</span>

 <span class="hljs-comment">### With 8 Cores, 8 Workers (Optimal)</span>
 ```
 Time →
 Core <span class="hljs-number">1</span>: [Worker <span class="hljs-number">1</span> ████████████████]
 Core <span class="hljs-number">2</span>: [Worker <span class="hljs-number">2</span> ████████████████]
 Core <span class="hljs-number">3</span>: [Worker <span class="hljs-number">3</span> ████████████████]
 Core <span class="hljs-number">4</span>: [Worker <span class="hljs-number">4</span> ████████████████]
 Core <span class="hljs-number">5</span>: [Worker <span class="hljs-number">5</span> ████████████████]
 Core <span class="hljs-number">6</span>: [Worker <span class="hljs-number">6</span> ████████████████]
 Core <span class="hljs-number">7</span>: [Worker <span class="hljs-number">7</span> ████████████████]
 Core <span class="hljs-number">8</span>: [Worker <span class="hljs-number">8</span> ████████████████]

 Each worker gets dedicated CPU time = FAST
 ```

 <span class="hljs-comment">### With 8 Cores, 16 Workers (Oversubscribed)</span>
 ```
 Time →
 Core <span class="hljs-number">1</span>: [W1 ██][W9 ██][W1 ██][W9 ██]  ← Context switching
 Core <span class="hljs-number">2</span>: [W2 ██][W10 ██][W2 ██][W10 ██]
 Core <span class="hljs-number">3</span>: [W3 ██][W11 ██][W3 ██][W11 ██]
 Core <span class="hljs-number">4</span>: [W4 ██][W12 ██][W4 ██][W12 ██]
 Core <span class="hljs-number">5</span>: [W5 ██][W13 ██][W5 ██][W13 ██]
 Core <span class="hljs-number">6</span>: [W6 ██][W14 ██][W6 ██][W14 ██]
 Core <span class="hljs-number">7</span>: [W7 ██][W15 ██][W7 ██][W15 ██]
 Core <span class="hljs-number">8</span>: [W8 ██][W16 ██][W8 ██][W16 ██]

 Workers fight <span class="hljs-keyword">for</span> CPU time = OVERHEAD
</code></pre>
</li>
<li><p><strong>Shared Resources</strong></p>
<p> Think of this like <code>all 10 painters trying to use the same brush at once</code> That could be chaotic. Things like Database connections, File handling that includes reading, writing, etc, HTTP requests, Memory, and variables. For example:</p>
<pre><code class="lang-python"> <span class="hljs-comment"># WRONG - File handle can't be shared</span>
 file = open(<span class="hljs-string">'data.txt'</span>, <span class="hljs-string">'w'</span>)

 <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">worker</span>(<span class="hljs-params">data</span>):</span>
     file.write(data)  <span class="hljs-comment"># Will crash</span>

 <span class="hljs-keyword">with</span> Pool(<span class="hljs-number">5</span>) <span class="hljs-keyword">as</span> pool:
     pool.map(worker, [<span class="hljs-string">'data1'</span>, <span class="hljs-string">'data2'</span>])

 <span class="hljs-comment"># CORRECT - Each process opens its own file</span>
 <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">worker</span>(<span class="hljs-params">data</span>):</span>
     <span class="hljs-keyword">with</span> open(<span class="hljs-string">f'data_<span class="hljs-subst">{os.getpid()}</span>.txt'</span>, <span class="hljs-string">'w'</span>) <span class="hljs-keyword">as</span> file:
         file.write(data)
</code></pre>
</li>
<li><p><strong>The multiprocessing library has a manager that can manage variables</strong></p>
<p> From above, we have already established that shared resources are tricky to handle in parallel. So how do you handle this?.</p>
<ol>
<li><p>For non-mutating variables, it’s fine; each worker will get a copy of the global variable</p>
<pre><code class="lang-python"> LARGE_LOOKUP_TABLE = {<span class="hljs-string">'painter_name'</span>: <span class="hljs-string">'Patrick'</span>, ...}

 <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">worker</span>(<span class="hljs-params">item</span>):</span>
     value = LARGE_LOOKUP_TABLE.get(item)
</code></pre>
</li>
<li><p>Shared Variables</p>
<pre><code class="lang-python"> <span class="hljs-keyword">from</span> multiprocessing <span class="hljs-keyword">import</span> Value, Array, Manager

 <span class="hljs-comment"># Simple</span>
 counter = Value(<span class="hljs-string">'i'</span>, <span class="hljs-number">0</span>)  
 <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">worker</span>(<span class="hljs-params">n, counter</span>):</span>
     <span class="hljs-keyword">with</span> counter.get_lock():
         counter.value += <span class="hljs-number">1</span>

 <span class="hljs-comment"># Complex</span>
 manager = Manager()
 results_list = manager.list() 
 results_dict = manager.dict()
</code></pre>
</li>
</ol>
</li>
</ol>
<h2 id="heading-when-to-use-multiprocessing">When to use <code>Multiprocessing</code></h2>
<p>As I sign out, as you are ready to prompt that agent to rewrite your backend APIs to use parallelism, there are things you need to consider.</p>
<p><strong>Good for:</strong></p>
<ul>
<li><p>I/O bound tasks (database queries, API calls)</p>
</li>
<li><p>CPU-intensive tasks with independent work units</p>
</li>
<li><p>When you have many similar tasks</p>
</li>
</ul>
<p><strong>Not good for:</strong></p>
<ul>
<li><p>Tasks that need to share state frequently</p>
</li>
<li><p>Simple, fast operations (overhead might make it slower)</p>
</li>
<li><p>When you're near memory limits</p>
</li>
</ul>
<p>This is just an introduction. Let me know if you are interested in advanced stuff like process intercommunications, which are quite similar to <code>Golang</code> channels, but a bit complicated.<br />Adios ✌️</p>
]]></content:encoded></item><item><title><![CDATA[WebRTC for Audio Spaces: Key Architecture Considerations]]></title><description><![CDATA[Well, I’m no expert. I have been playing with webRTC and related technologies, such as Asterisk, ever since I joined tech professionally.
However, I have seen experiments, different strategies, scaling web conferences, and “fancy” tools. Throughout m...]]></description><link>https://blog.iampato.me/webrtc-for-audio-spaces-key-architecture-considerations</link><guid isPermaLink="true">https://blog.iampato.me/webrtc-for-audio-spaces-key-architecture-considerations</guid><category><![CDATA[WebRTC]]></category><dc:creator><![CDATA[Patrick Waweru]]></dc:creator><pubDate>Tue, 03 Dec 2024 07:28:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/73o_FzZ5x-w/upload/338636cfc4024bb9646319bf9ad03341.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Well, I’m no expert. I have been playing with webRTC and related technologies, such as Asterisk, ever since I joined tech professionally.</p>
<p>However, I have seen experiments, different strategies, scaling web conferences, and “fancy” tools. Throughout my professional career, I’ve come to truly value the importance of understanding the fundamentals, especially the workings of the underlying infrastructure. In this blog, we’ll dive into the specifics of scaling audio streaming applications or features, such as X (formerly Twitter) Spaces.</p>
<p><img src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExcWU5cnBkaHZuZWxkbTQzdXFzYXNsejNnZHFrOTBncGY1MHdoYjE5biZlcD12MV9naWZzX3NlYXJjaCZjdD1n/3jcgPn9fzfaXc1EHJC/giphy.gif" alt class="image--center mx-auto" /></p>
<h3 id="heading-webrtc-architecture">WebRTC Architecture</h3>
<p>Without wasting much of your time: SFU vs MCU, is a war that can be debated till Christ returns to the world for the believers.</p>
<p>A <strong>Selective forward Unit</strong> (SFU) that differs from a p2p is a media server that receives media from each party in a conference call, decides which streams should be forwarded to other parties, and then forwards them. So if you have three clients on a call each client will have three remote streams and one local stream.</p>
<p>A <strong>Multipoint Control Unit</strong> (MCU) works by mixing multiple media streams into a single stream, with higher server processing due to transcoding and mixing hence you need a big server for this which results in lower bandwidth usage for clients but higher latency. SFU will save you on server bills while compromising on latency.</p>
<h3 id="heading-industry-recommendations">Industry Recommendations</h3>
<p><img src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExYnVpNGhweXU5aWw2ZHduZzl0cnlqamE0YWJncWMyMDl3ejk1d2dtMyZlcD12MV9naWZzX3NlYXJjaCZjdD1n/A28YVGI2KT84WcbJ1A/giphy.gif" alt class="image--center mx-auto" /></p>
<p><strong>Participants,</strong> for calls with an average of fewer than 5 participants, use SFU for its efficiency and low latency. If the call involves more than 5 participants, opt for MCU to prioritize bandwidth efficiency.</p>
<p>Wondering? why I’m not talking about audio vs video vs audio + video, focus guys were are building the next generational X audio spaces.</p>
<h3 id="heading-our-million-dollar-audio-rooms-app">Our Million dollar Audio Rooms app</h3>
<p><strong>Problem:</strong> sometimes our rooms have less than 5 people, it’s midnight of the night, and night owls want to catch up there is no shame in that. Automatically you would recommend SFU, but there is a problem during peak hours on average rooms have over 50 people in them automatically you rule our SFU for MCU.</p>
<p><strong>My Implementation Strategy:</strong> Use both SFU and MCU and upgrade or downgrade based on the number of participants. This dynamic mode selection isn’t straightforward as two things need to be catered for:</p>
<ol>
<li><p><em>Peer connections</em>: separate SFU and MCU connections are required.</p>
</li>
<li><p><em>Signaling Server:</em> another important piece of the puzzle, use your signaling server to send control messages to clients indicating when to switch modes. Then trigger WebRTC renegotiation to switch between SFU and MCU.</p>
</li>
</ol>
<p>For our use case below is what I could recommend:</p>
<ul>
<li><p><strong>Primary Model: SFU</strong> (Selective Forwarding Unit):</p>
<ul>
<li><p><strong>Speakers</strong> (e.g., 10–15 active participants): Use SFU to forward streams directly to other participants. This ensures low latency and reduces server-side processing.</p>
</li>
<li><p><strong>Listeners</strong> (e.g., 85+ passive participants): Instead of routing individual streams via SFU, mix speaker streams into a single audio stream and broadcast it (similar to an MCU for listeners only). This approach minimizes bandwidth usage for passive participants.</p>
</li>
<li><p><strong>Dynamic Role Switching</strong> Allow participants to move between "listener" and "speaker" roles dynamically:</p>
<ul>
<li><p>Listener → Speaker: Promote them to the SFU layer for real-time audio.</p>
</li>
<li><p>Speaker → Listener: Drop their individual SFU stream and include them in the mixed broadcast.</p>
</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>Backup Model</strong>: MCU for fallback (if you anticipate &gt;100 participants regularly).</p>
</li>
</ul>
<h4 id="heading-webrtc-media-server"><strong>WebRTC Media Server</strong></h4>
<p>Use a media server that supports both SFU and optional mixing (MCU-like) capabilities:</p>
<ul>
<li><p><a target="_blank" href="https://mediasoup.org/"><strong>Mediasoup</strong></a><strong>:</strong> A powerful SFU framework with simulcast support. You can simulate MCU by mixing streams for listeners using additional components like FFmpeg.</p>
</li>
<li><p><strong>Janus:</strong> Another flexible SFU with plugins for audio mixing.</p>
</li>
<li><p><a target="_blank" href="https://www.kurento.org/"><strong>Kurento</strong></a><strong>:</strong> Supports both SFU and MCU features natively.</p>
</li>
</ul>
<p>Honorable mentions, XDN architecture seems to be doing what I’m proposing above, I’m yet to test this personally but I will in the coming days: To read more about it <a target="_blank" href="https://www.red5.net/blog/xdn-architecture-traditional-cdns-need-not-apply/">click here</a></p>
<p><img src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExdm0xYWY0bDM5dTl1cnNnM2hsZWt6YTBwbGhwM2U2cjNkeGRpbDl4bSZlcD12MV9naWZzX3NlYXJjaCZjdD1n/26u4lOMA8JKSnL9Uk/giphy.gif" alt class="image--center mx-auto" /></p>
<p>That’s a wrap, see you on the next one… Adios ✌️</p>
]]></content:encoded></item><item><title><![CDATA[Part 1: Setting Up the Development Environment]]></title><description><![CDATA[In this first part of our series, we'll set up the development environment necessary to build our mini Whatsapp application. We'll be installing and configuring the essential tools and frameworks required for both the back end and the front end of ou...]]></description><link>https://blog.iampato.me/part-1-setting-up-the-development-environment</link><guid isPermaLink="true">https://blog.iampato.me/part-1-setting-up-the-development-environment</guid><category><![CDATA[Flutter]]></category><category><![CDATA[nestjs]]></category><category><![CDATA[chatapp]]></category><category><![CDATA[Platform Engineering ]]></category><dc:creator><![CDATA[Patrick Waweru]]></dc:creator><pubDate>Sun, 01 Sep 2024 21:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1726124153147/cd6ff54b-89a5-4e1d-a5e2-7386a8a83e72.avif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this first part of our series, we'll set up the development environment necessary to build our mini Whatsapp application. We'll be installing and configuring the essential tools and frameworks required for both the back end and the front end of our application.</p>
<h4 id="heading-step-1-installing-necessary-tools">Step 1: Installing Necessary Tools</h4>
<p>Before we dive into coding, we need to install the following tools:</p>
<ol>
<li><p><strong>Node.js and npm</strong>: Node.js is a JavaScript runtime used for building the backend, and npm is the package manager for Node.js.</p>
</li>
<li><p><strong>Flutter</strong>: Flutter is our framework for building the cross-platform mobile application.</p>
</li>
<li><p><strong>PostgreSQL</strong>: PostgreSQL will be our database.</p>
</li>
<li><p><strong>Docker</strong>: Docker will help us containerize our application.</p>
</li>
<li><p><strong>Kubernetes (k8s)</strong>: Kubernetes will manage the deployment of our containers.</p>
</li>
<li><p><strong>Terraform</strong>: Terraform will handle our infrastructure as code.</p>
</li>
</ol>
<h5 id="heading-installing-nodejs-and-npm">Installing Node.js and npm</h5>
<p>Download and install Node.js from the <a target="_blank" href="https://nodejs.org/">official website</a>. This will also install npm.</p>
<p>To verify the installation, run:</p>
<pre><code class="lang-sh">node -v
npm -v
</code></pre>
<h5 id="heading-installing-flutter">Installing Flutter</h5>
<p>Follow the instructions on the <a target="_blank" href="https://flutter.dev/docs/get-started/install">Flutter installation guide</a> to set up Flutter on your machine. After installation, verify by running:</p>
<pre><code class="lang-sh">flutter doctor
</code></pre>
<h5 id="heading-installing-postgresql">Installing PostgreSQL</h5>
<p>Download and install PostgreSQL from the <a target="_blank" href="https://www.postgresql.org/download/">official website</a>. Follow the instructions for your operating system.</p>
<h5 id="heading-installing-docker">Installing Docker</h5>
<p>Download and install Docker from the <a target="_blank" href="https://www.docker.com/products/docker-desktop">official website</a>. After installation, verify by running:</p>
<pre><code class="lang-sh">docker --version
</code></pre>
<h5 id="heading-installing-kubernetes-k8s">Installing Kubernetes (k8s)</h5>
<p>For local development, we can use <a target="_blank" href="https://minikube.sigs.k8s.io/docs/start/">Minikube</a> to run Kubernetes on our local machine. Follow the installation guide for your operating system.</p>
<h5 id="heading-installing-terraform">Installing Terraform</h5>
<p>Download and install Terraform from the <a target="_blank" href="https://www.terraform.io/downloads.html">official website</a>. Verify the installation by running:</p>
<pre><code class="lang-sh">terraform -v
</code></pre>
<h4 id="heading-step-2-setting-up-nestjs-for-the-backend">Step 2: Setting Up NestJS for the Backend</h4>
<p>NestJS is a powerful backend framework for building scalable server-side applications. Let's set it up:</p>
<ol>
<li><p>Create a new NestJS project:</p>
<pre><code class="lang-sh"> npm i -g @nestjs/cli
 nest new backend
</code></pre>
</li>
<li><p>Navigate to the project directory:</p>
<pre><code class="lang-sh"> <span class="hljs-built_in">cd</span> backend
</code></pre>
</li>
<li><p>Install the necessary dependencies:</p>
<pre><code class="lang-sh"> npm install @nestjs/typeorm typeorm pg
</code></pre>
</li>
<li><p>Create a new module for our authentication system:</p>
<pre><code class="lang-sh"> nest generate module auth
 nest generate module chat
 nest generate module contact
 nest generate module user
</code></pre>
</li>
</ol>
<h4 id="heading-step-3-initializing-a-flutter-project-for-the-frontend">Step 3: Initializing a Flutter Project for the Frontend</h4>
<p>Flutter will be used for building our cross-platform mobile application. Let's initialize a new Flutter project:</p>
<ol>
<li><p>Create a new Flutter project:</p>
<pre><code class="lang-sh"> flutter create frontend
</code></pre>
</li>
<li><p>Navigate to the project directory:</p>
<pre><code class="lang-sh"> <span class="hljs-built_in">cd</span> frontend
</code></pre>
</li>
<li><p>Open the project in your preferred IDE (VS Code, Android Studio, etc.).</p>
</li>
</ol>
<h4 id="heading-step-4-configuring-postgresql">Step 4: Configuring PostgreSQL</h4>
<ol>
<li><p>Start the PostgreSQL server and create a new database for our application:</p>
<pre><code class="lang-sh"> psql -U postgres -p *****
 CREATE DATABASE chat-production;
</code></pre>
</li>
<li><p>Update the NestJS project to connect to the PostgreSQL database. Edit the <code>app.module.ts</code> file:</p>
<pre><code class="lang-typescript"> <span class="hljs-comment">/// data source</span>
 <span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getAppDataSource</span>(<span class="hljs-params">
   configService: PsqlConfigService,
 </span>): <span class="hljs-title">PostgresConnectionOptions</span> </span>{
   <span class="hljs-keyword">const</span> config = configService.getConfig();
   <span class="hljs-keyword">return</span> {
     <span class="hljs-keyword">type</span>: <span class="hljs-string">'postgres'</span>,
     host: config.host,
     port: config.port,
     username: config.user,
     password: config.password,
     database: config.database,
     entities: [User],
     synchronize: <span class="hljs-literal">true</span>,
     ssl: [<span class="hljs-string">'production'</span>].includes(config.appEnv) &amp;&amp; {
       rejectUnauthorized: <span class="hljs-literal">false</span>,
     },
     migrationsRun: <span class="hljs-literal">true</span>,
     logging: <span class="hljs-literal">true</span>,
     <span class="hljs-comment">// logger: 'file',</span>
     migrations: [__dirname + <span class="hljs-string">'/migrations/**/*{.ts,.js}'</span>],
   };
 }

 <span class="hljs-comment">// app.module.ts</span>
 <span class="hljs-keyword">import</span> { Module } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;
 <span class="hljs-keyword">import</span> { TypeOrmModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/typeorm'</span>;
 <span class="hljs-keyword">import</span> { AuthModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'./auth/auth.module'</span>;

 <span class="hljs-meta">@Module</span>({
   imports: [
     TypeOrmModule.forRootAsync({
       imports: [ConfigModule],
       useFactory: <span class="hljs-function">(<span class="hljs-params">configService: PsqlConfigService</span>) =&gt;</span> {
         <span class="hljs-keyword">return</span> getAppDataSource(configService);
       },
       inject: [PsqlConfigService],
     }),
     AuthModule,
     ChatModule,
     ContactModule,
     PresenceModule,
     ConfigModule,
   ],
   controllers: [],
   providers: [],
 })
 <span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> AppModule {}
</code></pre>
</li>
</ol>
<h4 id="heading-step-5-running-the-application">Step 5: Running the Application</h4>
<ol>
<li><p>Start the NestJS backend server:</p>
<pre><code class="lang-sh"> npm run start:dev
</code></pre>
</li>
<li><p>Run the Flutter application:</p>
<pre><code class="lang-sh"> flutter run
</code></pre>
</li>
</ol>
<p>At this point, we have set up our development environment, including the necessary tools, the NestJS backend, and the Flutter front end. In the next part, we'll dive into building the authentication system for our mini Whatsapp application.</p>
<p>Stay tuned for Part 2: Building the Authentication System.</p>
]]></content:encoded></item><item><title><![CDATA[Introduction to Building a Mini Chatting App]]></title><description><![CDATA[I have many tips and opinions about building a mini-chat app. It's been on my mind, so why not create a series covering everything? It could include guides, tutorials, and commentary. With feedback, I can focus on what readers find most useful. Addin...]]></description><link>https://blog.iampato.me/introduction-to-building-a-mini-chatting-app</link><guid isPermaLink="true">https://blog.iampato.me/introduction-to-building-a-mini-chatting-app</guid><category><![CDATA[nestjs]]></category><category><![CDATA[Flutter]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[Terraform]]></category><category><![CDATA[chat application]]></category><dc:creator><![CDATA[Patrick Waweru]]></dc:creator><pubDate>Mon, 12 Aug 2024 18:15:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1723062171303/1dbf6a9d-0300-4acf-a528-eeb59d14f2f1.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I have many tips and opinions about building a mini-chat app. It's been on my mind, so why not create a series covering everything? It could include guides, tutorials, and commentary. With feedback, I can focus on what readers find most useful. Adding case studies, expert interviews, and practical examples will make it more engaging.</p>
<h3 id="heading-expectations">Expectations</h3>
<p>Let's clearly define and limit the expectations of what we will deliver at the end of this blog series. Setting realistic goals from the beginning is important to avoid misunderstandings.</p>
<p>No, you won't pitch the mini-chatting application to investors for funding. Additionally, you won't be taking it to market once we finish this series. Our primary aim is to provide a learning experience, focusing on the development process and the technical challenges involved.</p>
<p>At the end of the day, users will be able to:</p>
<ol>
<li><p>Sign in/sign up (based on whether an account record exists)</p>
</li>
<li><p>Sync contacts</p>
</li>
<li><p>Start a chat</p>
</li>
<li><p>Create a group</p>
</li>
<li><p>Chat with a group</p>
</li>
<li><p>Leave a group</p>
</li>
<li><p>See who is online</p>
</li>
</ol>
<p>Note: Users can only use text, no media sharing.</p>
<h3 id="heading-tools-used">Tools Used</h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Technology</td><td>Purpose</td></tr>
</thead>
<tbody>
<tr>
<td>NestJs</td><td>Our backend framework</td></tr>
<tr>
<td>Flutter App</td><td>Our cross-platform technology for building the app</td></tr>
<tr>
<td>Firebase Cloud Messaging</td><td>For signaling and event streaming</td></tr>
<tr>
<td>PostgreSQL</td><td>Our database for building relationships</td></tr>
<tr>
<td>Docker, k8s, and Terraform</td><td>For containerization, orchestration, and IAC</td></tr>
<tr>
<td>Redis</td><td>For scalable memory cache</td></tr>
</tbody>
</table>
</div><h3 id="heading-series-outline">Series Outline</h3>
<p><strong>Part 1: Setting Up the Development Environment</strong></p>
<ul>
<li><p>Installing necessary tools and dependencies</p>
</li>
<li><p>Setting up NestJS for the backend</p>
</li>
<li><p>Initializing a Flutter project for the frontend</p>
</li>
</ul>
<p><strong>Part 2: Building the Authentication System</strong></p>
<ul>
<li><p>Implementing sign-in and sign-up functionality</p>
</li>
<li><p>Integrating JWT for secure authentication</p>
</li>
</ul>
<p><strong>Part 3: Contact Synchronization</strong></p>
<ul>
<li><p>Creating a service for syncing contacts</p>
</li>
<li><p>Handling contact permissions and access</p>
</li>
</ul>
<p><strong>Part 4: Chat Functionality</strong></p>
<ul>
<li><p>Setting up the chat backend</p>
</li>
<li><p>Developing the chat UI in Flutter</p>
</li>
<li><p>Implementing real-time messaging using Firebase Cloud Messaging</p>
</li>
</ul>
<p><strong>Part 5: Group Chat Features</strong></p>
<ul>
<li><p>Creating and managing groups</p>
</li>
<li><p>Implementing group chat functionality</p>
</li>
<li><p>Handling group events like adding or removing members</p>
</li>
</ul>
<p><strong>Part 6: User Presence</strong></p>
<ul>
<li><p>Tracking online/offline status</p>
</li>
<li><p>Displaying user presence in the app</p>
</li>
</ul>
<p><strong>Part 7: Deployment and Scaling</strong></p>
<ul>
<li><p>Containerizing the application with Docker</p>
</li>
<li><p>Deploying with Kubernetes</p>
</li>
<li><p>Managing infrastructure with Terraform</p>
</li>
</ul>
<p><strong>Part 8: Final Touches and Best Practices</strong></p>
<ul>
<li><p>Ensuring code quality and performance</p>
</li>
<li><p>Implementing security best practices</p>
</li>
<li><p>Preparing the application for production use</p>
</li>
</ul>
<p>Stay tuned as we build our mini chatting app step-by-step. By the end, you'll understand the development process and have the skills to tackle similar projects. Let's get started!</p>
]]></content:encoded></item><item><title><![CDATA[The Curse of the Internal CRM: My Recurring Nightmare]]></title><description><![CDATA[When it happens repeatedly, not just once or twice, it ceases to be a mere coincidence. I start to believe that perhaps someone has placed a curse on all my jobs, if not on me. It seems like I always find myself in the same situation. For instance, I...]]></description><link>https://blog.iampato.me/the-curse-of-the-internal-crm-my-recurring-nightmare</link><guid isPermaLink="true">https://blog.iampato.me/the-curse-of-the-internal-crm-my-recurring-nightmare</guid><category><![CDATA[technology]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[Startups]]></category><category><![CDATA[startup]]></category><dc:creator><![CDATA[Patrick Waweru]]></dc:creator><pubDate>Wed, 07 Aug 2024 20:10:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/2EJCSULRwC8/upload/149c06dd961252f073ef8297f4b65d04.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When it happens repeatedly, not just once or twice, it ceases to be a mere coincidence. I start to believe that perhaps someone has placed a curse on all my jobs, if not on me. It seems like I always find myself in the same situation. For instance, I once built an internal tool, which primarily consisted of various dashboards, to address some of the recurring issues. Despite my efforts, the same pattern seems to persist, making me question the underlying causes.</p>
<p>No matter the role—whether it's a mobile engineer, frontend engineer, Fullstack, or DevOps—within the first year, I have to be involved in an internal CRM project.</p>
<h3 id="heading-choosing-the-right-tool">Choosing the right tool</h3>
<p>The stage of the organization can provide a clear answer to this question. In the early stages of a startup, the engineering team's primary focus is on building a Minimum Viable Product (MVP) as quickly and easily as possible. This is the ideal scenario for utilizing no-code tools, which allow for rapid development and iteration without the need for extensive coding skills.</p>
<p>As the organization evolves and moves into later stages, the focus shifts towards developing proprietary software. This is a phase where the engineering team can truly showcase its technical prowess and expertise by delivering sophisticated, custom-built software solutions that are tailored to the specific needs of the business. At this point, the emphasis is on creating robust, scalable, and high-performance applications that can support the growing demands of the organization.</p>
<h3 id="heading-summary">Summary</h3>
<p>I've noticed a recurring issue in my career: I often work on internal CRM/dashboard projects, regardless of my role. In early startup stages, no-code tools are great for quick MVP development. But as the company grows, the focus shifts to creating robust, scalable proprietary software to meet specific business needs.</p>
<p>What types of challenges do you believe you face? Let me know in the comments section.</p>
]]></content:encoded></item><item><title><![CDATA[React Native State vs. Props: Knowing the Difference]]></title><description><![CDATA[When developing React Native applications, understanding the concepts of state and props is fundamental. Both state and props play crucial roles in managing data and passing information between components, but they have different purposes and use cas...]]></description><link>https://blog.iampato.me/react-native-state-vs-props-knowing-the-difference</link><guid isPermaLink="true">https://blog.iampato.me/react-native-state-vs-props-knowing-the-difference</guid><category><![CDATA[React Native]]></category><category><![CDATA[State Management ]]></category><category><![CDATA[Props in reactjs]]></category><dc:creator><![CDATA[Patrick Waweru]]></dc:creator><pubDate>Tue, 01 Aug 2023 22:44:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1690929679620/708d069e-979b-4d6b-a5be-1979b08b1b0d.avif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When developing React Native applications, understanding the concepts of state and props is fundamental. Both state and props play crucial roles in managing data and passing information between components, but they have different purposes and use cases. In this blog post, we'll delve into the differences between React Native state and props and how to use them effectively in your mobile app development.</p>
<h2 id="heading-what-are-props">What are Props?</h2>
<p><strong>Props</strong> (short for properties) are a mechanism for passing data from a parent component to a child component in React Native. Props are immutable, meaning that their values cannot be changed once they are set by the parent component. They are a way for components to communicate and share information with one another.</p>
<p>When you define a component in React Native, you can pass data to it by setting attributes, or props, on the component tag. The component can then access and use this data as needed. Props are read-only within the child component, and any changes to the data must come from the parent component.</p>
<h2 id="heading-how-to-use-props">How to Use Props?</h2>
<p>Let's look at a simple example to understand how to use props in React Native with TypeScript. Suppose we have a <code>User</code> component that receives a user's name as a prop and displays a greeting message.</p>
<p>First, install TypeScript and the necessary dependencies:</p>
<pre><code class="lang-bash">npm install --save react react-native react-native-cli typescript
</code></pre>
<p>Now, create a file named <code>User.tsx</code> and add the following code:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { View, Text, StyleSheet } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native'</span>;

<span class="hljs-keyword">interface</span> UserProps {
  name: <span class="hljs-built_in">string</span>;
}

<span class="hljs-keyword">const</span> User: React.FC&lt;UserProps&gt; = <span class="hljs-function">(<span class="hljs-params">{ name }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    &lt;View style={styles.container}&gt;
      &lt;Text&gt;Hello, {name}!&lt;/Text&gt;
    &lt;/View&gt;
  );
};

<span class="hljs-keyword">const</span> styles = StyleSheet.create({
  container: {
    alignItems: <span class="hljs-string">'center'</span>,
    justifyContent: <span class="hljs-string">'center'</span>,
    padding: <span class="hljs-number">16</span>,
  },
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> User;
</code></pre>
<p>In this example, we define the <code>User</code> the component is a functional component that receives a prop called <code>name</code>. Inside the component, we use destructuring to extract the <code>name</code> prop and display a greeting message using it.</p>
<p>To use this component, create another file, e.g., <code>App.tsx</code>, with the following code:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { View, StyleSheet } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native'</span>;
<span class="hljs-keyword">import</span> User <span class="hljs-keyword">from</span> <span class="hljs-string">'./User'</span>;

<span class="hljs-keyword">const</span> App: React.FC = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    &lt;View style={styles.container}&gt;
      &lt;User name=<span class="hljs-string">"John Doe"</span> /&gt;
    &lt;/View&gt;
  );
};

<span class="hljs-keyword">const</span> styles = StyleSheet.create({
  container: {
    flex: <span class="hljs-number">1</span>,
    justifyContent: <span class="hljs-string">'center'</span>,
    alignItems: <span class="hljs-string">'center'</span>,
  },
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>In this <code>App</code> component, we use the <code>User</code> component and pass the <code>name</code> prop with the value "John Doe." The <code>User</code> component will receive this prop and display the greeting message accordingly.</p>
<h2 id="heading-what-is-state">What is State?</h2>
<p><strong>State</strong>, on the other hand, represents the internal data and dynamic values of a component. Unlike props, state is mutable and can be changed within the component itself. When the state of a component is updated, React re-renders the component to reflect the changes in the UI.</p>
<p>State is useful for storing data that may change during the component's lifecycle, such as user input, toggling UI elements, or loading data asynchronously.</p>
<h2 id="heading-how-to-use-state">How to Use State?</h2>
<p>Let's extend our previous example to demonstrate how to use state in React Native with TypeScript. Suppose we want to add a button to the <code>User</code> component that allows users to toggle a message.</p>
<p>Update the <code>User.tsx</code> file as follows:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { View, Text, StyleSheet, Button } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native'</span>;

<span class="hljs-keyword">interface</span> UserProps {
  name: <span class="hljs-built_in">string</span>;
}

<span class="hljs-keyword">const</span> User: React.FC&lt;UserProps&gt; = <span class="hljs-function">(<span class="hljs-params">{ name }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [showMessage, setShowMessage] = useState(<span class="hljs-literal">false</span>);

  <span class="hljs-keyword">const</span> toggleMessage = <span class="hljs-function">() =&gt;</span> {
    setShowMessage(!showMessage);
  };

  <span class="hljs-keyword">return</span> (
    &lt;View style={styles.container}&gt;
      &lt;Text&gt;Hello, {name}!&lt;/Text&gt;
      {showMessage &amp;&amp; &lt;Text&gt;Have a great day!&lt;/Text&gt;}
      &lt;Button title={showMessage ? <span class="hljs-string">'Hide Message'</span> : <span class="hljs-string">'Show Message'</span>} onPress={toggleMessage} /&gt;
    &lt;/View&gt;
  );
};

<span class="hljs-keyword">const</span> styles = StyleSheet.create({
  container: {
    alignItems: <span class="hljs-string">'center'</span>,
    justifyContent: <span class="hljs-string">'center'</span>,
    padding: <span class="hljs-number">16</span>,
  },
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> User;
</code></pre>
<p>In this updated <code>User</code> component, we've introduced a new state variable called <code>showMessage</code> using the <code>useState</code> hook. We've also added a <code>toggleMessage</code> function to toggle the state between <code>true</code> and <code>false</code> when the button is pressed.</p>
<p>Now, the <code>User</code> component will display a "Show Message" button. When the button is pressed, the additional message "Have a great day!" will appear below the greeting message. Pressing the button again will hide the message.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In summary, React Native <strong>props</strong> are used to pass data from a parent component to a child component and are immutable, while <strong>state</strong> is used to manage internal data within a component and is mutable. Understanding the distinction between state and props is essential for building efficient and maintainable React Native applications.</p>
<p>By utilizing both props and state effectively, you can create interactive and dynamic user interfaces that respond to user interactions and data changes.</p>
<p>Remember that in TypeScript, it's crucial to define the types for your props and states using interfaces or types, as demonstrated in the examples above. Doing so will provide type safety and help catch potential errors during development.</p>
<p>I hope this blog post has clarified the difference between React Native state and props and provided you with the knowledge to use them confidently in your future projects. Happy coding!</p>
<hr />
<p>Note: The code examples provided in this blog assume that you have already set up a basic React Native project with TypeScript configurations.</p>
]]></content:encoded></item><item><title><![CDATA[Mastering React Native App States: The Ultimate Guide to Smooth User Experiences]]></title><description><![CDATA[A well-liked framework for creating cross-platform mobile applications in React Native. The detection of the various states that an app may be in, such as when it is launched, resumed, or detached, is one of the difficulties in developing mobile apps...]]></description><link>https://blog.iampato.me/mastering-react-native-app-states-the-ultimate-guide-to-smooth-user-experiences</link><guid isPermaLink="true">https://blog.iampato.me/mastering-react-native-app-states-the-ultimate-guide-to-smooth-user-experiences</guid><category><![CDATA[React Native]]></category><category><![CDATA[Android]]></category><category><![CDATA[react native app development]]></category><dc:creator><![CDATA[Patrick Waweru]]></dc:creator><pubDate>Tue, 21 Mar 2023 17:31:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1679396775482/6731d783-dc07-4604-a6f7-fc1e287b9327.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A well-liked framework for creating cross-platform mobile applications in React Native. The detection of the various states that an app may be in, such as when it is launched, resumed, or detached, is one of the difficulties in developing mobile apps. In this blog post, we'll look at how React Native can detect app states.</p>
<h3 id="heading-app-state-api">App State API</h3>
<p>React Native provides an App State API that allows you to detect changes in the state of your application. The App State API exposes several different states that your app can be in, including:</p>
<ul>
<li><p>active: the app is in the foreground and the user is interacting with it</p>
</li>
<li><p>background: the app is in the background and not visible to the user</p>
</li>
<li><p>inactive: the app is transitioning between foreground and background, or vice versa</p>
</li>
<li><p>suspended: the app is no longer running in the background and has been suspended by the system</p>
</li>
</ul>
<h3 id="heading-detecting-app-state"><strong>Detecting App State</strong></h3>
<p>React Native provides the AppState API to detect the current state of the application. The AppState API has two methods:</p>
<ul>
<li><p>addEventListener(): This method registers a listener function that will be called whenever the app state changes.</p>
</li>
<li><p>removeEventListener(): This method removes the listener function that was previously registered with addEventListener().</p>
</li>
</ul>
<p>Here's an example of how to use the AppState API:</p>
<p>To use the App State API, you need to import the AppState module from the React Native core library. Once you have imported the module, you can add an event listener to detect changes in the app state. Here's an example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { AppState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-native'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span> </span>{
  state = {
    <span class="hljs-attr">appState</span>: AppState.currentState
  };

  componentDidMount() {
    AppState.addEventListener(<span class="hljs-string">'change'</span>, <span class="hljs-built_in">this</span>.handleAppStateChange);
  }

  componentWillUnmount() {
    AppState.removeEventListener(<span class="hljs-string">'change'</span>, <span class="hljs-built_in">this</span>.handleAppStateChange);
  }

  handleAppStateChange = <span class="hljs-function">(<span class="hljs-params">nextAppState</span>) =&gt;</span> {
    <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">appState</span>: nextAppState });
  };

  render() {
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">View</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>&gt;</span>Current state: {this.state.appState}<span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">View</span>&gt;</span></span>
    );
  }
}
</code></pre>
<p>And if you are using Functional components, we import the <code>AppState</code> module from React Native and use the <code>useState</code> and <code>useEffect</code> hooks to manage the state of the application. We also register a listener function using the <code>addEventListener()</code> method, which updates the state whenever the app state changes. here is a code snippet</p>
<pre><code class="lang-javascript">....
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> handleAppStateChange = <span class="hljs-function">(<span class="hljs-params">nextAppState</span>) =&gt;</span> {
      setAppState(nextAppState);
    };

    AppState.addEventListener(<span class="hljs-string">'change'</span>, handleAppStateChange);

    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      AppState.removeEventListener(<span class="hljs-string">'change'</span>, handleAppStateChange);
    };
  }, []);
....
</code></pre>
<p>In the class example, we are using the <code>AppState.currentState</code> property to get the current state of the app when the component mounts. Using the method, we then add an event listener for changes in the app state. When the app state changes, the <code>handleAppStateChange()</code> the method is called, which updates the state of the app.</p>
<p>In conclusion, for React Native applications to provide a seamless user experience, app state detection is essential. Developers can make sure that their apps are reliable and responsive even in difficult circumstances by understanding the various states and putting proper techniques in place to handle them.</p>
<p>Detecting app states is a crucial component of React Native development, whether it's dealing with network connectivity issues, controlling memory use, or responding to system events. Developers may produce high-quality apps that fulfill customers' demands and expectations by being proactive and cautious in this area.</p>
<p>Detecting app states may be an easy and simple job with the correct methods and tools. Developers may make sure their apps are reliable and stable by adhering to best practices and monitoring the app's activity constantly. Enjoy</p>
]]></content:encoded></item><item><title><![CDATA[Firebase cloud messaging and python 3]]></title><description><![CDATA[It is one thing to acquire users and another to retain them. One way of maintaining users is to keep them engaged is via notifications and Firebase Cloud Messaging can help in delivering these notifications.
The objective of this tutorial is to show ...]]></description><link>https://blog.iampato.me/firebase-cloud-messaging-and-python-3</link><guid isPermaLink="true">https://blog.iampato.me/firebase-cloud-messaging-and-python-3</guid><category><![CDATA[Firebase]]></category><category><![CDATA[push notifications]]></category><category><![CDATA[Python 3]]></category><category><![CDATA[Flutter]]></category><dc:creator><![CDATA[Patrick Waweru]]></dc:creator><pubDate>Sat, 08 Jan 2022 14:30:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1641470999977/RCEH0D_ea.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It is one thing to acquire users and another to retain them. One way of maintaining users is to keep them engaged is via notifications and Firebase Cloud Messaging can help in delivering these notifications.
The objective of this tutorial is to show you how to send messages to your users via two methods, one using registration tokens and the second using topics; which is a less popular method that I think people don't know that much.
Code examples shall be done in python but the concepts can be applied to other languages. ( just a disclaimer)</p>
<h2 id="heading-lets-get-started">Let's get started</h2>
<p>For this tutorial, I shall assume you have python installed on your computer and <code>pip</code>, python package manager.</p>
<p>Pre-steps:</p>
<ul>
<li>Head over to <a target="_blank" href="https://console.firebase.google.com/">Firebase console</a> and create a project</li>
<li><p>Create a service account; visit this <a target="_blank" href="https://console.cloud.google.com/projectselector/iam-admin/serviceaccounts/create?supportedpurview=project">link</a>. Remember you can select a project as demonstrated below
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1641651408213/5YDtyOdpE.png" alt="image (8).png" /></p>
</li>
<li><p>Create or upload keys; once you have created a service account, you shall be redirected to the page with all service accounts available, Tap on the key that has the name <strong>firebase-adminsdk</strong>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1641651800135/-VWv83yH8o.png" alt="image (9).png" /></p>
</li>
<li><p>Download a <strong>credential json</strong> file; navigate to the <strong>keys</strong> tab and tap the <strong>Add Key</strong> button, choose <strong>JSON</strong> key type, and automatically it should download a credential json file</p>
</li>
</ul>
<h2 id="heading-lets-write-some-code">let's write some code</h2>
<p>I am intending to write a utils class that you can always reuse while maintaining a cleaner code type of style.
Firebase has developed a PyPI library that makes it easy to use firebase service with python so run this:</p>
<pre><code class="lang-bash">pip install firebase-admin
</code></pre>
<p>Create a file named <code>fcm_utils.py</code> and paste the following </p>
<pre><code><span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> Any
<span class="hljs-keyword">from</span> firebase_admin <span class="hljs-keyword">import</span> messaging, credentials
<span class="hljs-keyword">import</span> firebase_admin


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FcmUtils</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self</span>):</span>
        creds = credentials.Certificate(
            <span class="hljs-string">'utils/nilipie-9d6b9-0dbc5b6385b9.json'</span>)
        default_app = firebase_admin.initialize_app(creds)

    <span class="hljs-comment"># send_to_token</span>
    <span class="hljs-comment"># Send a message to a specific token</span>
    <span class="hljs-comment"># registration_token: The token to send the message to</span>
    <span class="hljs-comment"># data: The data to send to the token</span>
    <span class="hljs-comment"># {</span>
    <span class="hljs-comment">#   'score': '850',</span>
    <span class="hljs-comment">#   'time': '2:45',</span>
    <span class="hljs-comment"># },</span>
    <span class="hljs-comment"># example</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">send_to_token</span>(<span class="hljs-params">self, registration_token, title, body, data=None</span>) -&gt; Any:</span>
        message = messaging.Message(
            notification=messaging.Notification(
                title=title,
                body=body,
            ),
            data=data,
            token=registration_token
        )
        response = messaging.send(message)
        print(response)
        <span class="hljs-keyword">return</span> response

    <span class="hljs-comment"># send_to_token_multicast</span>
    <span class="hljs-comment"># Send a message to a specific tokens</span>
    <span class="hljs-comment"># registration_tokens: The tokens to send the message to</span>
    <span class="hljs-comment"># data: The data to send to the tokens</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">send_to_token_multicast</span>(<span class="hljs-params">self, registration_tokens, title, body, data=None</span>) -&gt; Any:</span>
        <span class="hljs-comment"># registration_tokens has to be a list</span>
        <span class="hljs-keyword">assert</span> isinstance(registration_tokens, list)

        message = messaging.MulticastMessage(
            notification=messaging.Notification(
                title=title,
                body=body,
            ),
            data=data,
            token=registration_tokens
        )
        response = messaging.send_multicast(message)
        print(response)
        <span class="hljs-comment"># See the BatchResponse reference documentation</span>
        <span class="hljs-comment"># for the contents of response.</span>
        <span class="hljs-keyword">return</span> response

    <span class="hljs-comment"># send_to_topic</span>
    <span class="hljs-comment"># Send a message to a topic</span>
    <span class="hljs-comment"># topic: The topic to send the message to</span>
    <span class="hljs-comment"># data: The data to send to the topic</span>
    <span class="hljs-comment"># {</span>
    <span class="hljs-comment">#   'score': '850',</span>
    <span class="hljs-comment">#   'time': '2:45',</span>
    <span class="hljs-comment"># },</span>
    <span class="hljs-comment"># example</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">send_to_topic</span>(<span class="hljs-params">self, topic, title, body, data=None</span>) -&gt; Any:</span>
        message = messaging.Message(
            notification=messaging.Notification(
                title=title,
                body=body,
            ),
            data=data,
            topic=topic
        )
        response = messaging.send(message)
        print(response)
        <span class="hljs-comment"># Response is a message ID string.</span>
        <span class="hljs-keyword">return</span> response
</code></pre><p>Note: Don't forget to replace this line <code>utils/nilipie-9d6b9-0dbc5b6385b9.json</code> with the path to your JSON file.</p>
<p>The <code>FcmUtils</code> class exposes three methods:</p>
<ol>
<li><p><code>send_to_token</code> 
Sends a message to a specific token</p>
</li>
<li><p><code>send_to_token_multicast</code>
Practically the same as sending to a token instead you can send to one or many tokens in one request, hence it accepts a list of tokens (strings)</p>
</li>
<li><p><code>send_to_topic</code>
The last method sends a message to a specific topic, i.e clients need to be subscribed to this topic</p>
</li>
</ol>
<p>Now the util class can be used as follows:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fcm_utils <span class="hljs-keyword">import</span> FcmUtils

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span>():</span>
    messaging = FcmUtils()
    messaging.send_to_topic(<span class="hljs-string">"topics-all"</span>, <span class="hljs-string">"title"</span>, <span class="hljs-string">"body from topic"</span>)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    main()
</code></pre>
<p>Results:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1641557721026/Y0Qz8cUzY.png" alt="Screenshot_1641557702.png" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>That was fun and easy, hope you learned something, and please comment if you have any queries... just as a by the way the mobile screenshot is a <strong>Flutter</strong> app running on an Android emulator.</p>
]]></content:encoded></item><item><title><![CDATA[Using more than one Event channels in Flutter]]></title><description><![CDATA[Hello there, it's been a minute ...
Introduction
All those seasoned Flutter/Android/iOS developers know that at the end of the day, Flutter apps are just android and iOS apps on the Android Platform and iOS platform respectively and if you didn't kno...]]></description><link>https://blog.iampato.me/using-more-than-one-event-channels-in-flutter</link><guid isPermaLink="true">https://blog.iampato.me/using-more-than-one-event-channels-in-flutter</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Flutter Examples]]></category><dc:creator><![CDATA[Patrick Waweru]]></dc:creator><pubDate>Mon, 28 Jun 2021 22:01:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1623868672322/nbAXdkghN.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hello there, it's been a minute ...</p>
<h1 id="introduction">Introduction</h1>
<p>All those seasoned Flutter/Android/iOS developers know that at the end of the day, Flutter apps are just android and iOS apps on the Android Platform and iOS platform respectively and if you didn't know now you know.
So in order to access platform API(s) or Introduce new features through libraries available on Android or iOS, you need to write Platform channels that the Flutter engine can communicate using. So far they are three available channels: (1) Method Channels, (2) Event Channels, and the last one Native Views.</p>
<p><strong>Method Channels</strong>,  provide a way of communicating with Platform-specific code/APIs asynchronously, meaning if Flutter code calls a Platform code/API if the call returns a value the flutter code will have to async-wait the value. For more information on this please read this  <a target="_blank" href="https://flutter.dev/docs/development/platform-integration/platform-channels">official documentation</a>.</p>
<p><strong>Native Views</strong>, Native views for lack of better words puncture the Flutter engine and renders a native View in Flutter, For example: using native views you can render an Android EditText or iOS UITextField. Interesting most popular flutter plugin using this method example the Official Flutter Google Maps plugin  <a target="_blank" href="https://pub.dev/packages/google_maps_flutter">Link here</a>  to render Google maps.</p>
<p><strong>Event Channels</strong>, and now to the order of the day, event channels also to keep things simple and stupid they are like streams now in this case, events can be sent from the Platform side to the Flutter side, like how normal stream work.</p>
<p>This article will talk about having more than one event channel in one code base, The motivation for this article is; I am involved in a project that challenged me while working with event channels because most online resources show you how to add one only.</p>
<h1 id="lets-get-to-it">Let's get to it</h1>
<p>In this article, we shall create an example that will have two event channels one will emit the current timestamp and the other zero to infinity.</p>
<p>Create a new flutter project:
<code>flutter create two_eventchannels</code></p>
<p>Inside your project root directory open the <code>android</code> folder with <code>Android Studio</code> for better syntax highlighting and code completion.
Wait for Gradle to do its thing ..... and yes we shall be writing some <code>Kotlin</code></p>
<p>Your android studio should look something like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1624917369522/xCUzN18Oq.png" alt="Screenshot from 2021-06-28 23-32-38.png" /></p>
<p>Open the <code>MainActivity.kt</code> file should have:</p>
<pre><code><span class="hljs-selector-tag">package</span> <span class="hljs-selector-tag">com</span><span class="hljs-selector-class">.example</span><span class="hljs-selector-class">.two_eventchannels</span>

<span class="hljs-selector-tag">import</span> <span class="hljs-selector-tag">io</span><span class="hljs-selector-class">.flutter</span><span class="hljs-selector-class">.embedding</span><span class="hljs-selector-class">.android</span><span class="hljs-selector-class">.FlutterActivity</span>

<span class="hljs-selector-tag">class</span> <span class="hljs-selector-tag">MainActivity</span>: <span class="hljs-selector-tag">FlutterActivity</span>() {

}
</code></pre><p>Let's declare our event channels:</p>
<pre><code>...
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span>: <span class="hljs-type">FlutterActivity</span></span>() {
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> eventChannel1 = <span class="hljs-string">"com.example.two_eventchannels/events1"</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> eventChannel2 = <span class="hljs-string">"com.example.two_eventchannels/events2"</span>
}
...
</code></pre><p>Then override <code>configureFlutterEngine</code> that comes from <code>FlutterActivity</code></p>
<pre><code>  <span class="hljs-selector-tag">override</span> <span class="hljs-selector-tag">fun</span> <span class="hljs-selector-tag">configureFlutterEngine</span>(<span class="hljs-variable">@NonNull</span> <span class="hljs-attribute">flutterEngine</span>: FlutterEngine) {
        <span class="hljs-selector-tag">super</span><span class="hljs-selector-class">.configureFlutterEngine</span>(flutterEngine)
        <span class="hljs-selector-tag">EventChannel</span>(flutterEngine.dartExecutor.binaryMessenger, eventChannel1)
        <span class="hljs-selector-tag">EventChannel</span>(flutterEngine.dartExecutor.binaryMessenger, eventChannel2)
    }
</code></pre><p>So that the code looks like 👆</p>
<p>Let create our stream handler, I shall start with the one for streaming current time:</p>
<pre><code><span class="hljs-keyword">object</span> TimeHandler : EventChannel.StreamHandler {
    <span class="hljs-comment">// Handle event in main thread.</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> handler = Handler(Looper.getMainLooper())

    <span class="hljs-comment">// Declare our eventSink later it will be initialized</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> eventSink: EventChannel.EventSink? = <span class="hljs-literal">null</span>

    <span class="hljs-meta">@SuppressLint(<span class="hljs-meta-string">"SimpleDateFormat"</span>)</span>
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onListen</span><span class="hljs-params">(p0: <span class="hljs-type">Any</span>?, sink: <span class="hljs-type">EventChannel</span>.<span class="hljs-type">EventSink</span>)</span></span> {
        eventSink = sink
        <span class="hljs-comment">// every second send the time</span>
        <span class="hljs-keyword">val</span> r: Runnable = <span class="hljs-keyword">object</span> : Runnable {
            <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">run</span><span class="hljs-params">()</span></span> {
                handler.post {
                    <span class="hljs-keyword">val</span> dateFormat = SimpleDateFormat(<span class="hljs-string">"HH:mm:ss"</span>)
                    <span class="hljs-keyword">val</span> time = dateFormat.format(Date())
                    eventSink?.success(time)
                }
                handler.postDelayed(<span class="hljs-keyword">this</span>, <span class="hljs-number">1000</span>)
            }
        }
        handler.postDelayed(r, <span class="hljs-number">1000</span>)
    }

    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onCancel</span><span class="hljs-params">(p0: <span class="hljs-type">Any</span>?)</span></span> {
        eventSink = <span class="hljs-literal">null</span>
    }
}
</code></pre><p>Basic we have declared a singleton class called TimeHandler that extends EventChannel.StreamHandler gives us two overrides <code>onCancel</code> and <code>onListen</code> which is of importance to us.
Also, we have declared our OS <code>handler</code> and passed <code>Looper.getMainLooper()</code> so that the Handler can run on the <code>UI thread</code> and after a second we get the current time and sink it to our stream.</p>
<p>We shall do similar things with the Counter one:</p>
<pre><code><span class="hljs-keyword">object</span> CounterHandler : EventChannel.StreamHandler {
    <span class="hljs-comment">// Handle event in main thread.</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> handler = Handler(Looper.getMainLooper())

    <span class="hljs-comment">// Declare our eventSink later it will be initialized</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> eventSink: EventChannel.EventSink? = <span class="hljs-literal">null</span>

    <span class="hljs-meta">@SuppressLint(<span class="hljs-meta-string">"SimpleDateFormat"</span>)</span>
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onListen</span><span class="hljs-params">(p0: <span class="hljs-type">Any</span>?, sink: <span class="hljs-type">EventChannel</span>.<span class="hljs-type">EventSink</span>)</span></span> {
        eventSink = sink
        <span class="hljs-keyword">var</span> count: <span class="hljs-built_in">Int</span> = <span class="hljs-number">0</span>
        <span class="hljs-comment">// every 5 second send the time</span>
        <span class="hljs-keyword">val</span> r: Runnable = <span class="hljs-keyword">object</span> : Runnable {
            <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">run</span><span class="hljs-params">()</span></span> {
                handler.post {
                    count ++;
                    eventSink?.success(count)
                }
                handler.postDelayed(<span class="hljs-keyword">this</span>, <span class="hljs-number">1000</span>)
            }
        }
        handler.postDelayed(r, <span class="hljs-number">1000</span>)
    }

    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onCancel</span><span class="hljs-params">(p0: <span class="hljs-type">Any</span>?)</span></span> {
        eventSink = <span class="hljs-literal">null</span>
    }
}
</code></pre><p>Now that is done before heading over to the dart world we need to set our stream handlers on the event channels we declared. After that your code should look like this:</p>
<pre><code><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> : <span class="hljs-type">FlutterActivity</span></span>() {
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> eventChannel1 = <span class="hljs-string">"com.example.two_eventchannels/events1"</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> eventChannel2 = <span class="hljs-string">"com.example.two_eventchannels/events2"</span>

    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">configureFlutterEngine</span><span class="hljs-params">(<span class="hljs-meta">@NonNull</span> flutterEngine: <span class="hljs-type">FlutterEngine</span>)</span></span> {
        <span class="hljs-keyword">super</span>.configureFlutterEngine(flutterEngine)
        EventChannel(flutterEngine.dartExecutor.binaryMessenger, eventChannel2).setStreamHandler(
            CounterHandler
        )
        EventChannel(flutterEngine.dartExecutor.binaryMessenger, eventChannel1).setStreamHandler(
            TimeHandler
        )
    }
}

<span class="hljs-keyword">object</span> TimeHandler : EventChannel.StreamHandler {
    <span class="hljs-comment">// Handle event in main thread.</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> handler = Handler(Looper.getMainLooper())

    <span class="hljs-comment">// Declare our eventSink later it will be initialized</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> eventSink: EventChannel.EventSink? = <span class="hljs-literal">null</span>

    <span class="hljs-meta">@SuppressLint(<span class="hljs-meta-string">"SimpleDateFormat"</span>)</span>
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onListen</span><span class="hljs-params">(p0: <span class="hljs-type">Any</span>?, sink: <span class="hljs-type">EventChannel</span>.<span class="hljs-type">EventSink</span>)</span></span> {
        eventSink = sink
        <span class="hljs-comment">// every second send the time</span>
        <span class="hljs-keyword">val</span> r: Runnable = <span class="hljs-keyword">object</span> : Runnable {
            <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">run</span><span class="hljs-params">()</span></span> {
                handler.post {
                    <span class="hljs-keyword">val</span> dateFormat = SimpleDateFormat(<span class="hljs-string">"HH:mm:ss"</span>)
                    <span class="hljs-keyword">val</span> time = dateFormat.format(Date())
                    eventSink?.success(time)
                }
                handler.postDelayed(<span class="hljs-keyword">this</span>, <span class="hljs-number">1000</span>)
            }
        }
        handler.postDelayed(r, <span class="hljs-number">1000</span>)
    }

    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onCancel</span><span class="hljs-params">(p0: <span class="hljs-type">Any</span>?)</span></span> {
        eventSink = <span class="hljs-literal">null</span>
    }
}

<span class="hljs-keyword">object</span> CounterHandler : EventChannel.StreamHandler {
    <span class="hljs-comment">// Handle event in main thread.</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> handler = Handler(Looper.getMainLooper())

    <span class="hljs-comment">// Declare our eventSink later it will be initialized</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> eventSink: EventChannel.EventSink? = <span class="hljs-literal">null</span>

    <span class="hljs-meta">@SuppressLint(<span class="hljs-meta-string">"SimpleDateFormat"</span>)</span>
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onListen</span><span class="hljs-params">(p0: <span class="hljs-type">Any</span>?, sink: <span class="hljs-type">EventChannel</span>.<span class="hljs-type">EventSink</span>)</span></span> {
        eventSink = sink
        <span class="hljs-keyword">var</span> count: <span class="hljs-built_in">Int</span> = <span class="hljs-number">0</span>
        <span class="hljs-comment">// every 5 second send the time</span>
        <span class="hljs-keyword">val</span> r: Runnable = <span class="hljs-keyword">object</span> : Runnable {
            <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">run</span><span class="hljs-params">()</span></span> {
                handler.post {
                    count ++;
                    eventSink?.success(count)
                }
                handler.postDelayed(<span class="hljs-keyword">this</span>, <span class="hljs-number">1000</span>)
            }
        }
        handler.postDelayed(r, <span class="hljs-number">1000</span>)
    }

    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onCancel</span><span class="hljs-params">(p0: <span class="hljs-type">Any</span>?)</span></span> {
        eventSink = <span class="hljs-literal">null</span>
    }
}
</code></pre><h1 id="almost-done">Almost done</h1>
<p>Now let's write some dart code that called these event channels</p>
<pre><code>import <span class="hljs-string">'package:flutter/services.dart'</span>;

<span class="hljs-function">Stream&lt;String&gt; <span class="hljs-title">streamTimeFromNative</span>(<span class="hljs-params"></span>)</span> {
  <span class="hljs-keyword">const</span> _timeChannel =
      <span class="hljs-function"><span class="hljs-keyword">const</span> <span class="hljs-title">EventChannel</span>(<span class="hljs-params"><span class="hljs-string">'com.example.two_eventchannels/events1'</span></span>)</span>;
  <span class="hljs-keyword">return</span> _timeChannel.receiveBroadcastStream().map((<span class="hljs-keyword">event</span>) =&gt; <span class="hljs-keyword">event</span>.toString());
}

<span class="hljs-function">Stream&lt;<span class="hljs-keyword">int</span>&gt; <span class="hljs-title">streamCounterFromNative</span>(<span class="hljs-params"></span>)</span> {
  <span class="hljs-keyword">const</span> _counterChannel =
      <span class="hljs-function"><span class="hljs-keyword">const</span> <span class="hljs-title">EventChannel</span>(<span class="hljs-params"><span class="hljs-string">'com.example.two_eventchannels/events2'</span></span>)</span>;
  <span class="hljs-keyword">return</span> _counterChannel.receiveBroadcastStream().map((<span class="hljs-keyword">event</span>) {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">int</span>.parse(<span class="hljs-keyword">event</span>.toString());
  });
}
</code></pre><p>Without tickering with the boilerplate <code>flutter create</code> creates we shall edit the code to:</p>
<pre><code>Widget build(BuildContext context) {
    <span class="hljs-keyword">return</span> Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: <span class="hljs-keyword">Column</span>(
          mainAxisAlignment: MainAxisAlignment.center,
          children: &lt;Widget&gt;[
            Text(
              <span class="hljs-string">'Timer :'</span>,
            ),
            StreamBuilder&lt;String&gt;(
              stream: streamTimeFromNative(),
              builder: (context, <span class="hljs-keyword">snapshot</span>) {
                <span class="hljs-keyword">if</span> (<span class="hljs-keyword">snapshot</span>.hasData) {
                  <span class="hljs-keyword">return</span> Text(
                    <span class="hljs-string">'${snapshot.data}'</span>,
                    style: Theme.<span class="hljs-keyword">of</span>(context).textTheme.headline4,
                  );
                } <span class="hljs-keyword">else</span> {
                  <span class="hljs-keyword">return</span> CircularProgressIndicator();
                }
              },
            ),
            SizedBox(height: <span class="hljs-number">30</span>),
            Text(
              <span class="hljs-string">'Counter :'</span>,
            ),
            StreamBuilder&lt;<span class="hljs-type">int</span>&gt;(
              stream: streamCounterFromNative(),
              builder: (context, <span class="hljs-keyword">snapshot</span>) {
                <span class="hljs-keyword">if</span> (<span class="hljs-keyword">snapshot</span>.hasData) {
                  <span class="hljs-keyword">return</span> Text(
                    <span class="hljs-string">'${snapshot.data}'</span>,
                    style: Theme.<span class="hljs-keyword">of</span>(context).textTheme.headline4,
                  );
                } <span class="hljs-keyword">else</span> {
                  <span class="hljs-keyword">return</span> CircularProgressIndicator();
                }
              },
            ),
          ],
        ),
      ),
    );
  }
</code></pre><p>Then run your project:
Source code can be found here: <a target="_blank" href="https://github.com/iampato/Flutter-Event-Channels">link</a></p>
<p>Demo:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1624917222255/5y3SADamF.gif" alt="event .gif" /></p>
]]></content:encoded></item><item><title><![CDATA[Introduction first.]]></title><description><![CDATA[Hey everyone, and welcome to my blog page. First thing first this is my first ever blogging experience so if you notice something I might improve just let me know down in the comments section below.
Who I am?
My name is Patrick Waweru as of the date ...]]></description><link>https://blog.iampato.me/introduction-first</link><guid isPermaLink="true">https://blog.iampato.me/introduction-first</guid><category><![CDATA[software development]]></category><category><![CDATA[Flutter]]></category><category><![CDATA[Kotlin]]></category><category><![CDATA[Go Language]]></category><dc:creator><![CDATA[Patrick Waweru]]></dc:creator><pubDate>Mon, 19 Apr 2021 19:06:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1618677514778/HjoNb7Yfg.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hey everyone, and welcome to my blog page. First thing first this is my first ever blogging experience so if you notice something I might improve just let me know down in the comments section below.</p>
<h3 id="who-i-am">Who I am?</h3>
<p>My name is Patrick Waweru as of the date of writing this article currently 22 years of age. Currently located in Nairobi, Kenya. Currently, I am an employee of Ally Innovation that uses technology to inspire lives. My role there is as a Flutter developer with a keen emphasis on the UI and UX of their products.</p>
<h3 id="my-journey-into-tech">My journey into tech</h3>
<p>To cut the long story short, My serious journey into programming started in my second year of University at Dedan Kimathi University of Technology. Will attending one of the tech events organized back then is when I got started.</p>
<h3 id="what-to-expect">What to expect</h3>
<p>Lots of articles on simple and easy Flutter tips, Clean architecture according to my opinion, Golang simple examples, and hacks, a little of Java/Kotlin here and there and general tech topics.</p>
]]></content:encoded></item></channel></rss>