<?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" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by MuindiStephen on Medium]]></title>
        <description><![CDATA[Stories by MuindiStephen on Medium]]></description>
        <link>https://medium.com/@stephenmuindi241?source=rss-4e7ea133ff73------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*3j26x8kSJ7DjpCAY</url>
            <title>Stories by MuindiStephen on Medium</title>
            <link>https://medium.com/@stephenmuindi241?source=rss-4e7ea133ff73------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 30 May 2026 17:39:01 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@stephenmuindi241/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Using Data for Better Farmer Outcomes]]></title>
            <link>https://medium.com/@stephenmuindi241/using-data-for-better-farmer-outcomes-b3ee28166702?source=rss-4e7ea133ff73------2</link>
            <guid isPermaLink="false">https://medium.com/p/b3ee28166702</guid>
            <category><![CDATA[digital-tools]]></category>
            <category><![CDATA[agritech]]></category>
            <dc:creator><![CDATA[MuindiStephen]]></dc:creator>
            <pubDate>Thu, 10 Jul 2025 12:54:03 GMT</pubDate>
            <atom:updated>2025-07-10T12:54:03.580Z</atom:updated>
            <content:encoded><![CDATA[<h3>Abstract</h3><p>This article explores how data-driven tools and platforms can transform agricultural outcomes for smallholder farmers in Kenya and across East Africa. It reflects on real-world experiences from AgriSasa, a mobile app designed to provide actionable insights to farmers through GPS mapping, weather integration, crop cycle tracking, and market access. The piece highlights the critical role of ethical data collection, interoperability, and inclusive digital design in scaling impact. It also argues for stronger public data infrastructure to support equitable agricultural innovation.</p><h3>Using Data for Better Farmer Outcomes</h3><p>Agriculture remains the backbone of most African economies, yet smallholder farmers face numerous challenges ranging from unpredictable weather patterns to limited access to markets, financing, and agronomic advice. With the right digital tools and data systems, these challenges can be transformed into opportunities for growth.</p><p>As the lead developer of AgriSasa, I have seen how structured data collection and mobile accessibility can empower farmers with information to make better decisions. Farmers using the app receive customized crop cycle guidance based on their farm’s GPS location, input costs, and expected harvest timelines. This data not only improves productivity but also supports smarter use of inputs, reduces wastage, and enhances food security.</p><p>Furthermore, data-driven platforms can unlock access to financial services. By tracking expenses and income over time, a farmer’s digital financial profile can support loan eligibility and insurance access — key levers for rural economic development. However, for such systems to thrive, we need secure, interoperable digital public infrastructure. Without shared standards, open APIs, and farmer-centric data protection policies, progress risks being fragmented and exclusionary.</p><p>To maximize impact, Africa must invest in DPI that connects existing innovations, ensures ethical data usage, and brings together government, private sector, and civil society. Tools like AgriSasa are promising, but scalability and sustainability require a supportive ecosystem of trust, policy, and interoperability.</p><p>Copyright 2025: Stephen Muindi</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b3ee28166702" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Shared Flow — Observable]]></title>
            <link>https://medium.com/@stephenmuindi241/shared-flow-observable-a44271a77b02?source=rss-4e7ea133ff73------2</link>
            <guid isPermaLink="false">https://medium.com/p/a44271a77b02</guid>
            <dc:creator><![CDATA[MuindiStephen]]></dc:creator>
            <pubDate>Thu, 31 Oct 2024 07:00:17 GMT</pubDate>
            <atom:updated>2024-10-31T07:00:17.519Z</atom:updated>
            <content:encoded><![CDATA[<h3>Shared Flow — Observable</h3><p><a href="https://medium.com/@riztech.dev/using-sharedflow-in-android-a-complete-guide-with-code-examples-90e6baa0ba0f">https://medium.com/@riztech.dev/using-sharedflow-in-android-a-complete-guide-with-code-examples-90e6baa0ba0f</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a44271a77b02" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Android Development]]></title>
            <link>https://medium.com/@stephenmuindi241/android-development-1cfa85ef472e?source=rss-4e7ea133ff73------2</link>
            <guid isPermaLink="false">https://medium.com/p/1cfa85ef472e</guid>
            <category><![CDATA[android]]></category>
            <dc:creator><![CDATA[MuindiStephen]]></dc:creator>
            <pubDate>Mon, 07 Oct 2024 08:59:56 GMT</pubDate>
            <atom:updated>2024-10-07T08:59:56.572Z</atom:updated>
            <content:encoded><![CDATA[<p>Android Development</p><ul><li>Boosting and simplifying code and productivity</li><li>Read below article</li></ul><p><a href="https://blog.stackademic.com/exploring-the-magic-of-kotlin-delegation-simplifying-code-and-boosting-productivity-0160a5a853bc">https://blog.stackademic.com/exploring-the-magic-of-kotlin-delegation-simplifying-code-and-boosting-productivity-0160a5a853bc</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1cfa85ef472e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to externalise the Base URL in Retrofit for Android]]></title>
            <link>https://medium.com/@stephenmuindi241/how-to-externalise-the-base-url-in-retrofit-for-android-aea9800581b0?source=rss-4e7ea133ff73------2</link>
            <guid isPermaLink="false">https://medium.com/p/aea9800581b0</guid>
            <category><![CDATA[androiddev]]></category>
            <category><![CDATA[base-url]]></category>
            <category><![CDATA[android]]></category>
            <dc:creator><![CDATA[MuindiStephen]]></dc:creator>
            <pubDate>Mon, 20 May 2024 11:01:22 GMT</pubDate>
            <atom:updated>2024-05-20T11:02:26.292Z</atom:updated>
            <content:encoded><![CDATA[<p>You have an Android app now that are working fine using Retrofit. You are trying to automate the build for testing and production release, to reduce the chance of human error (i.e. dev forget to point the Base URL to production when build for production..etc)</p><p>Imagine that the Base URL for Retrofit are defined in the class file. Is there any method that we can use to configure it to be in a properties file or xml so that we can use the Gradle script to pick the right file to be included with the build?</p><p>Here is a solution…</p><p>You can define a constant in your buildTypes and then use it in the retrofit builder:</p><pre><br><br>buildTypes {<br>    debug {<br>        buildConfigField &quot;String&quot;, &quot;API_URL&quot;, &quot;\&quot;https://url/pre/\&quot;&quot;<br>    }<br>    release {<br>        buildConfigField &quot;String&quot;, &quot;API_URL&quot;, &quot;\&quot;https://url/pro/\&quot;&quot;<br>    }<br>}<br></pre><pre><br><br>Retrofit retrofit = new Retrofit.Builder()<br>    .baseUrl(BuildConfig.API_URL)<br>    .build();</pre><p>Notice that if you have different modules the BuildConfig is defined in each of them. For this cases I define the buildTypes in the app module and pass the BuildConfig.API_URL as parameter in the call to the module with the retrofit builder.</p><p>Oops! Hope you learned something.</p><p>Follow for more!</p><p>https://github.com/MuindiStephen</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=aea9800581b0" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What Do you prefer using Delegates.notNull() or lateinit Kotlin?]]></title>
            <link>https://medium.com/@stephenmuindi241/what-do-you-prefer-using-delegates-notnull-or-lateinit-kotlin-b473c71d3e81?source=rss-4e7ea133ff73------2</link>
            <guid isPermaLink="false">https://medium.com/p/b473c71d3e81</guid>
            <category><![CDATA[kotlin]]></category>
            <category><![CDATA[android]]></category>
            <dc:creator><![CDATA[MuindiStephen]]></dc:creator>
            <pubDate>Tue, 07 May 2024 13:21:28 GMT</pubDate>
            <atom:updated>2024-05-07T13:21:28.197Z</atom:updated>
            <content:encoded><![CDATA[<p>Hey guys, welcome to another technical blog.</p><p>I was looking for the model to use between the above two but both look and works pretty similar especially during initialization of variable in android. But which one should you go for?</p><p>Below is an example of their usage.</p><pre>private var mMediaController by Delegates.notNull&lt;MediaControllerCompat&gt;()<br><br>or<br><br>lateinit private var mMediaController: MediaControllerCompat</pre><p>Let’s look into maybe their similarities and how they differ:</p><pre>- notNull creates an extra object for each property.<br><br>- The object is small, but if you have lots of properties, it can be significant for you.<br><br>- You can&#39;t use the notNull delegate with external injection tools that injects directly to Java fields;<br><br>- You can&#39;t create a lateinit property of the primitive type (Int, Long, etc).<br><br>- lateinit is cheaper, but you can use only the delegate when your property has a primitive type.</pre><p>Key takeaways:</p><ol><li><a href="https://discuss.kotlinlang.org/t/notnull-delegate-vs-lateinit/1923">https://discuss.kotlinlang.org/t/notnull-delegate-vs-lateinit/1923</a></li></ol><p>Follow for more: https://x.com/MuindiStephen_</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b473c71d3e81" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why Requests are called “wrappers” rather than “payloads” in the context of frameworks like…]]></title>
            <link>https://medium.com/@stephenmuindi241/why-requests-are-called-wrappers-rather-than-payloads-in-the-context-of-frameworks-like-e586d54a8ae9?source=rss-4e7ea133ff73------2</link>
            <guid isPermaLink="false">https://medium.com/p/e586d54a8ae9</guid>
            <category><![CDATA[java]]></category>
            <category><![CDATA[springboot-3]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[MuindiStephen]]></dc:creator>
            <pubDate>Wed, 21 Feb 2024 06:41:23 GMT</pubDate>
            <atom:updated>2024-02-21T06:41:23.872Z</atom:updated>
            <content:encoded><![CDATA[<h3>Why Requests are called “wrappers” rather than “payloads” in the context of frameworks like spring-boot</h3><p>Requests are often calls made by the client to a specific api server.</p><p>Below is a sample POJO class in springboot that contains a request. This is the most commonly used naming of packages.</p><pre>package com.example.springbootdemo.payload;<br><br><br>@Getter<br>@Setter<br>@NoArgsConstructor<br>@AllArgsConstructor<br>public class RegisterRequest{<br> @Email(message = “Email should be valid”)<br> private String email;<br> @Size(min = 3, max = 15, message = “First Name should be between 3 and 15 characters”)<br> private String firstName;<br> @Size(min=3,max=15, message = “Last Name should be between 3 and 15 characters”)<br> private String lastName;<br> @Min (value = 1, message = “Select user profile”)<br> private long profileId;<br>}</pre><p>However,<strong> ‘payloads’ </strong>means actual data being transmitted without focusing on how it is being encapsulated. Payloads could be in form of json, xml or raw data.</p><p>Now, referring requests as <strong>‘wrappers’</strong> means that the request is enclosed or wrapped within an object that provides additional information or context. Such additional information could be headers, cookies and metadata.</p><p>Wrapper sample class:</p><pre>package com.example.springbootdemo.wrappers;<br><br>@Getter<br>@Setter<br>@NoArgsConstructor<br>@AllArgsConstructor<br>public class RegisterUserWrapper{<br> @Email(message = &quot;Email should be valid&quot;)<br> private String email;<br> @Size(min = 3, max = 15, message = &quot;First Name should be between 3 and 15 characters&quot;)<br> private String firstName;<br> @Size(min=3,max=15, message = &quot;Last Name should be between 3 and 15 characters&quot;)<br> private String lastName;<br> @Min (value = 1, message = &quot;Select user profile&quot;)<br> private long profileId;<br>}</pre><p>Finally, developers refer requests are “payloads” or “wrappers” to emphazise different aspects of the request.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e586d54a8ae9" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[My Experience As a GDSC lead at Kibabii University(2022–2023) year.]]></title>
            <link>https://medium.com/@stephenmuindi241/my-experience-as-a-gdsc-lead-at-kibabii-university-2022-2023-year-64b61019f9bd?source=rss-4e7ea133ff73------2</link>
            <guid isPermaLink="false">https://medium.com/p/64b61019f9bd</guid>
            <category><![CDATA[gdsc-lead]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[gdsc]]></category>
            <category><![CDATA[google]]></category>
            <dc:creator><![CDATA[MuindiStephen]]></dc:creator>
            <pubDate>Sat, 08 Jul 2023 09:30:34 GMT</pubDate>
            <atom:updated>2024-02-21T08:30:44.746Z</atom:updated>
            <content:encoded><![CDATA[<p>Hello, My name is Stephen Muindi a.k.a Steve MD. I greet you with lots of excitement like in a razzmatazz show.</p><p>Okay someone may questioningly asks, “What is GDSC? What does it do?”.</p><p>Alright, I have Answers for you at my fingertips. GDSC means Google Developer Student Clubs.</p><blockquote>Google Developer Student Clubs are university based community groups for students interested in Google developer technologies. Students from all undergraduate or graduate programs with an interest in growing as a developer are welcome. By joining a GDSC, students grow their knowledge in a peer-to-peer learning environment and build solutions for local businesses and their community.</blockquote><p><strong>Learn more here :)</strong></p><p><a href="https://gdsc.community.dev/">About GDSC | Google Developer Student Clubs</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/868/1*4-F52xnaKNqKuV_D_Budww.png" /><figcaption>GDSC lead @ August 16th,2022</figcaption></figure><p>When I received this email, joy, surprise, and emotional happiness filled my heart and my presence seeing a nice congratulatory message to me. I felt like let me jump into it and take up the opportunity.</p><p>Initially, I felt like it was not the so-called ‘thing’ and I just gained the courage to volunteer for the opportunity, as the English people quote:</p><blockquote>If you have a dream, don’t just sit there. Gather courage to believe that you can succeed and leave no stone unturned to make it a reality.</blockquote><p>This was when I used to be a very active member of the GDSC club and passionate about tech, however, previous GDSC leads and colleagues referred me because they believed in me and my experience. Thank you to previous GDSC leads for referring me.</p><p>I am honored to share with you the experience I have got, the ups and downs, and boom we are here as the tech community.</p><p><strong>My Experience</strong></p><p>I remember first when I received the email, I shared with GDSC members and my friends that I was chosen to be the Lead, and they encouraged me.</p><p>6 more co-leads joined and a Patron to make the club going.</p><p>Fortunately, there is a very amazing tech club called <strong>Kibabii Informatics Club </strong>that we organized collaboration events with and made a success. Thanks to the club executive lead. We got in touch with the club while we learned various skills in a peer-to-peer environment. We learned various skills like Android(Kotlin), Declarative Ui with Jetpack compose, Cyber Security, Machine Learning, Data communication(Huawei), Flutter, Web Development, and many others.</p><p>I am thrilled to say, I have been impacted positively by being a participant in GDSC Kibabii University. It is what I usually say, eliminate the fear within yourself and grab the opportunity. I trusted in the journey, a journey full of more learning because you’re not the best in the field, and sharing your knowledge and skills along with your peers.</p><p>We too collaborated and networked with other campus GDSCs in some events.</p><p>Indeed, it is a big experience I would say.</p><p>Down here is one of the tech events we made it to happen online. Greetings and thank you to the speaker(<a href="https://medium.com/u/b8b6aea7cdb1">Joel Kanyi</a>).</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FaWc907dhkcg%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DaWc907dhkcg&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FaWc907dhkcg%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/7c54f00a1bc4f7be01bbd530d1fd3262/href">https://medium.com/media/7c54f00a1bc4f7be01bbd530d1fd3262/href</a></iframe><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FmW8TMpbYHAY%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DmW8TMpbYHAY&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FmW8TMpbYHAY%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/7a2951aae30f94cbbe0e8959da315046/href">https://medium.com/media/7a2951aae30f94cbbe0e8959da315046/href</a></iframe><p>A cybersecurity event by Roy Wanyoike, Congrats.</p><h4>A word to my fellow techies :)</h4><p>‘‘If you choose a certain path in your life and you believe in it, put more effort, it will be a door opening for the next step in your life.’’ — Stephen Muindi.</p><p>Thank you for believing in me and I believe I have impacted you much in technology. God bless you.</p><p>Want to reach out to me? Here are my socials.</p><p>Twitter : <a href="https://twitter.com/MuindiStephen_">https://twitter.com/MuindiStephen_</a></p><p>Linkedin: <a href="http://www.linkedin.com/in/stephen-muindi-3a31741a0">http://www.linkedin.com/in/stephen-muindi-3a31741a0</a></p><p>REMEMBER TO BUY ME COFFEE: <a href="https://www.buymeacoffee.com/stephenmui8">https://www.buymeacoffee.com/stephenmui8</a>?</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=64b61019f9bd" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[HashMap Data Structure in Kotlin for Android Development.]]></title>
            <link>https://medium.com/@stephenmuindi241/hashmap-data-structure-in-kotlin-for-android-development-bdc5370c3220?source=rss-4e7ea133ff73------2</link>
            <guid isPermaLink="false">https://medium.com/p/bdc5370c3220</guid>
            <category><![CDATA[hashmap-in-java]]></category>
            <category><![CDATA[data-structures]]></category>
            <category><![CDATA[kotlin]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[hashmap]]></category>
            <dc:creator><![CDATA[MuindiStephen]]></dc:creator>
            <pubDate>Sat, 24 Jun 2023 00:07:00 GMT</pubDate>
            <atom:updated>2023-06-24T00:07:00.146Z</atom:updated>
            <content:encoded><![CDATA[<p>The hashmap data structure is a collection of key and value pairs where each key is directed to a single value.</p><p>Hashmaps are very important in Android Development with Kotlin especially when you want to store data in the form of key-value pairs and may be <strong>looking up specific data</strong> or <strong>passing it from one screen to the next.</strong></p><p>Here is an example of a hashmap.</p><pre>var WithDrawMoneyDetails: HashMap&lt;String, Any&gt; = HashMap&lt;String, Any&gt;()<br>WithDrawMoneyDetails[&quot;phonenumber&quot;] = phoneNumber<br>WithDrawMoneyDetails[&quot;amount&quot;] = 1000<br><br><br>/**<br> A demonstration of taking phonenumber and amount for withdraw purposes<br>when you click withdrawMoneyButton<br>*/<br><br>// Now handle Viewmodel<br>withdrawMoneyViewModel.withDraw(withDrawMoneyDetails)</pre><p>Key TakeAways:</p><p><a href="https://www.bezkoder.com/kotlin-hashmap/">Kotlin HashMap tutorial with examples - BezKoder</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bdc5370c3220" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why you should use Flows instead of LiveData in Room Database?]]></title>
            <link>https://medium.com/@stephenmuindi241/why-you-should-use-flows-instead-of-livedata-in-room-database-77aa96d26873?source=rss-4e7ea133ff73------2</link>
            <guid isPermaLink="false">https://medium.com/p/77aa96d26873</guid>
            <category><![CDATA[android-lifecycle]]></category>
            <category><![CDATA[room-database]]></category>
            <category><![CDATA[android]]></category>
            <dc:creator><![CDATA[MuindiStephen]]></dc:creator>
            <pubDate>Tue, 13 Jun 2023 09:50:33 GMT</pubDate>
            <atom:updated>2023-06-13T09:51:45.758Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/345/1*dgqp8XP13FnohxtLA5tdow.png" /></figure><p>Flows are used to emit values to the Ui anytime when data stored in the room database is being updated, deleted or added.</p><p>Therefore,<strong> Flows</strong> are the best to make this possible.</p><p><strong>Livedata</strong> observes the changes made to the room database in the lifecycle and react to the app.</p><p>Flows makes it easier to test your app.</p><p>Livedata makes it difficult to test your app, because this observable sometimes misbehaves. It becomes an issue especially when sharing data across components and can lead to debugging issues.</p><p>Take a look at this Dao in Room database</p><pre>@Dao<br>interface ShoppingDao {<br>    @Insert(onConflict = OnConflictStrategy.REPLACE)<br>    suspend fun insertShoppingItem(shoppingItem: ShoppingItem)<br><br>    @Delete<br>    suspend fun deleteShoppingItem(shoppingItem: ShoppingItem)<br><br>    @Query(&quot;SELECT * FROM shopping_items&quot;)<br>    fun observeAllShoppingItems(): Flow&lt;List&lt;ShoppingItem&gt;&gt;<br>}</pre><pre>@Query(&quot;SELECT * FROM shopping_items&quot;)<br>    fun observeAllShoppingItems(): Flow&lt;List&lt;ShoppingItem&gt;&gt;<br> <br>// This code returns a flow of a list of all shopping items everytime from the <br>// room database</pre><h4>Key takeaways</h4><ul><li><a href="https://developer.android.com/training/data-storage/room">https://developer.android.com/training/data-storage/room</a></li></ul><p>Connect me at:</p><ul><li><a href="https://twitter.com/MuindiStephen_">JavaScript is not available.</a></li><li><a href="https://github.com/MuindiStephen">MuindiStephen - Overview</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=77aa96d26873" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Singleton Pattern in Room Database]]></title>
            <link>https://medium.com/@stephenmuindi241/singleton-pattern-in-room-database-566c250196aa?source=rss-4e7ea133ff73------2</link>
            <guid isPermaLink="false">https://medium.com/p/566c250196aa</guid>
            <category><![CDATA[room-database-caching]]></category>
            <category><![CDATA[room-database]]></category>
            <category><![CDATA[singleton-pattern]]></category>
            <category><![CDATA[android-room-database]]></category>
            <dc:creator><![CDATA[MuindiStephen]]></dc:creator>
            <pubDate>Thu, 08 Jun 2023 12:40:33 GMT</pubDate>
            <atom:updated>2023-06-08T12:40:33.559Z</atom:updated>
            <content:encoded><![CDATA[<h3>Introduction</h3><p>In this article, we will learn how to implement singleton patterns in Android.</p><p>Singleton pattern is of help, especially in approaches where your Android app needs to use a single instance of a class.</p><h4>Why do we need a singleton pattern in Room Database?</h4><p>In the Room database, we implement a singleton pattern by creating only one instance of the room database to avoid <strong>memory leaks</strong>. Memory leaks occur especially when you do not specify room database instances.</p><p>Having a number of room database instances can lead to memory leaks.</p><h4>Prerequisites</h4><ul><li><em>Basic knowledge of Kotlin programming language</em></li><li><em>Understanding of how to use the room database in Android</em></li><li><em>Knowledge of Android development using Kotlin</em></li><li><em>Basic knowledge and understanding of databases</em></li></ul><p>Room database works on top of SQLite database providing an offline abstract layer therefore bringing easeness to use and implement it in android.</p><p>Room database has 3 components that is dao[data access object], entity[can be a tableName], and the database[instance referred for storage]</p><p>Step 1: Open your Android studio and create an empty project and name it <strong>WordRoomDBSample</strong> as the project name</p><p>Step 2. Create a new Kotlin file called Word as an entity of type data class</p><p>Paste this code:</p><pre>import androidx.room.ColumnInfo<br>import androidx.room.Entity<br>import androidx.room.PrimaryKey<br><br><br>@Entity(tableName = &quot;word&quot;)<br>data class Word(<br>    @PrimaryKey(autoGenerate = true) val id: Int = 0,<br>    @ColumnInfo(name=&quot;name&quot;)val name: String?,<br>)</pre><p>Step 3: Create another new Kotlin file of type interface called WordDao</p><p>Paste this code:</p><pre><br>import androidx.room.*<br>import com.stevemd.unittesting.data.local.room.entity.Word<br>import kotlinx.coroutines.flow.Flow<br><br>@Dao<br>interface WordDao {<br><br>    @Query(&quot;SELECT * FROM word&quot;)<br>    fun getAllWords(): Flow&lt;List&lt;Word&gt;&gt;<br><br>    @Query(&quot;SELECT * FROM word where id = :wordId&quot;)<br>    suspend fun getOneWord(wordId: Int): Word<br><br>    @Insert<br>    suspend fun insertWord(word: Word)<br><br>    @Update<br>    suspend fun updateWord(word: Word)<br><br>    @Delete<br>    suspend fun deleteWord(word: Word)<br>}</pre><p>Step 4: Create another new Kotlin file called WordDatabase</p><pre>import android.content.Context<br>import androidx.room.Database<br>import androidx.room.Room<br>import androidx.room.RoomDatabase<br>import com.stevemd.unittesting.data.local.room.dao.WordDao<br>import com.stevemd.unittesting.data.local.room.entity.Word<br><br><br>@Database(entities = [Word::class], version = 1, exportSchema = false)<br>abstract class WordDatabase : RoomDatabase() {<br>    abstract fun wordDao(): WordDao<br><br>    companion object {<br>        private const val Database_NAME = &quot;words.db&quot;<br><br>        /**<br>         * As we need only one instance of db in our app will use to store<br>         * This is to avoid memory leaks in android when there exist multiple instances of db<br>         */<br>        @Volatile<br>        private var INSTANCE: WordDatabase? = null<br><br>        fun getInstance(context: Context): AppDatabase {<br><br>            synchronized(this) {<br>                var instance = INSTANCE<br><br>                if (instance == null) {<br>                    instance = Room.databaseBuilder(<br>                        context.applicationContext,<br>                        WordDatabase::class.java,<br>                        Database_NAME<br>                    ).build()<br><br>                    INSTANCE = instance<br>                }<br>                return instance<br>            }<br>        }<br>    }<br>}</pre><p>Here, in WordDatabase, we only have one defined instance which acts as a singleton to be used in the app.</p><h3>Key takeaways</h3><ul><li><a href="https://developer.android.com/training/data-storage/room">https://developer.android.com/training/data-storage/room</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=566c250196aa" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>