<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Aniket Bhoite</title>
    <description>The latest articles on DEV Community by Aniket Bhoite (@aniketbhoite).</description>
    <link>https://dev.to/aniketbhoite</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F790560%2F29298b5f-8b1a-42f0-ab02-4d6b2b7af0a0.jpeg</url>
      <title>DEV Community: Aniket Bhoite</title>
      <link>https://dev.to/aniketbhoite</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aniketbhoite"/>
    <language>en</language>
    <item>
      <title>Kotlin Flow: Simple yet Powerful Implementation</title>
      <dc:creator>Aniket Bhoite</dc:creator>
      <pubDate>Sat, 02 Sep 2023 17:55:18 +0000</pubDate>
      <link>https://dev.to/aniketbhoite/kotlin-flow-simple-yet-powerful-implementation-39jp</link>
      <guid>https://dev.to/aniketbhoite/kotlin-flow-simple-yet-powerful-implementation-39jp</guid>
      <description>&lt;p&gt;Ever since Flow was first introduced in Kotlin version 1.3.0, it has become an important and highly discussed topic in the Kotlin community. But why?&lt;/p&gt;

&lt;p&gt;Flow is a simple yet powerful implementation for asynchronous programming in Kotlin.&lt;/p&gt;

&lt;p&gt;Flow is nothing but a coroutine that returns multiple results. It allows developers to write structurally concurrent, asynchronous and non-blocking code in a sequential style. But what do all these technical terms means to new developers, it's hard to grasp all of them at once. It took me some time to understand it.&lt;/p&gt;

&lt;p&gt;The reason Flow can do this without being too expensive is because it has a very simple internal implementation. Flow is nothing but two interfaces and their functions calling each other. Let me explain, but first, forget for the moment anything you know about coroutines suspend function and all. &lt;/p&gt;

&lt;p&gt;Let's start.&lt;/p&gt;

&lt;p&gt;To understand how flow internally works, we only need to understand two main concepts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Interface and Anonymous Implementation of an Interface&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Functional interface, or a Single Abstract Method (SAM) interface in Kotlin&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s create two Flow interfaces.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Flow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;collector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;FlowCollector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;FlowCollector&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;



&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;outputStream&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;object&lt;/span&gt; &lt;span class="err"&gt;: &lt;/span&gt;&lt;span class="nc"&gt;Flow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;collector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;FlowCollector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="n"&gt;collector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"first"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;collector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"second"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;outputStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;object&lt;/span&gt; &lt;span class="err"&gt;: &lt;/span&gt;&lt;span class="nc"&gt;FlowCollector&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uppercase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

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


&lt;span class="cm"&gt;/*

OUTPUT:

first
FIRST
second
SECOND

 */&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;P.S: For simplicity, we are currently only considering the Flow type as a string.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That's it!! This is flow in its simplest and bare-bones form, and we have only used the first concept so far. As you can see, this is nothing but one function directly calling another one multiple times. &lt;/p&gt;

&lt;p&gt;Let's make this a little bit prettier by using a &lt;a href="https://kotlinlang.org/docs/fun-interfaces.html"&gt;Functional Interface &lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An interface with only one abstract method is called a &lt;strong&gt;Functional Interface&lt;/strong&gt; or a &lt;strong&gt;Single Abstract Method (SAM)&lt;/strong&gt; interface. The functional interface can have multiple non-abstract members but only one abstract member.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Flow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;collector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;FlowCollector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;FlowCollector&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;outputStream&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;object&lt;/span&gt; &lt;span class="err"&gt;: &lt;/span&gt;&lt;span class="nc"&gt;Flow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;collector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;FlowCollector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="n"&gt;collector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"first"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;collector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"second"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;outputStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uppercase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// SAME OUTPUT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's starting to look similar now. The anonymous implementation of the Flow interface is boilerplate code. This can be solved by using a top-level function with the Flow anonymous implementation as a return type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;flow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;FlowCollector&lt;/span&gt;&lt;span class="p"&gt;.()&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Flow&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;object&lt;/span&gt; &lt;span class="err"&gt;: &lt;/span&gt;&lt;span class="nc"&gt;Flow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;collector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;FlowCollector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;collector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;block&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Flow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;collector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;FlowCollector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;FlowCollector&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;outputStream&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;flow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"first"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"second"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="n"&gt;outputStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uppercase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;//SAME OUTPUT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the familiar-looking flow we use under the hood. This doesn’t appear to be as feature-rich as we mentioned above. In theory, any programming language can do this so what makes Kotlin so unique? The answer is Kotlin’s magic function keyword "&lt;strong&gt;suspend&lt;/strong&gt;”.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Flow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;suspend&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;collector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;FlowCollector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;FlowCollector&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;suspend&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Making functions suspendable means they can do much more than simple functions. Making these functions suspend ensures that flow can only be called from other suspend functions or coroutine builders. Try to remember what coroutines can do. Flow incorporates all the features of coroutine. For example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Structured Concurrency: The Flow Builder block (collect function) runs in the same coroutine scope as the flow collector block by default. So when the scope is stopped both the builder and collector blocks stops executing, saving precious CPU resources. No need to manually close the stream.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Asynchronous, non-blocking code: We can control which code decide which code should run which Dispatcher. This makes it very useful for running IO operations on Background threads without blocking the original/main thread.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sequential &amp;amp; Readable: Suspend functions wait for the result of other suspend functions in the order until then they remain in a suspending state without blocking the thread.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Back Pressure: The Flow Builder and Collector block runs on the same coroutine so when collector block is processing result, the Builder block is suspended to prevent it from producing unnecessary results that may not be processed by the Builder block. This special feature comes with flow by default. Other libraries have to do fancy workarounds to achieve this.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And many more features like this.&lt;/p&gt;

&lt;p&gt;One of the flagship features of Flow is its operator functions. Are they complex to understand? No, because flow is nothing more than simple function calling each other. So, if we create an extension function with a flow as a return type, we can theoretically accomplish anything. Let’s look at the &lt;code&gt;onStart&lt;/code&gt; and &lt;code&gt;onCompletion&lt;/code&gt; operator functions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nc"&gt;Flow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onStart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;FlowCollector&lt;/span&gt;&lt;span class="p"&gt;.()&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;flow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;action&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nc"&gt;Flow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onCompletion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;FlowCollector&lt;/span&gt;&lt;span class="p"&gt;.()&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;flow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;action&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="o"&gt;......&lt;/span&gt;

&lt;span class="n"&gt;outputStream&lt;/span&gt;
   &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onStart&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"onStart"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onCompletion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"onComplete"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uppercase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="cm"&gt;/*

OUTPUT:

onStart
first
FIRST
second
SECOND
onComplete

 */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;PS: This is a highly simplified explanation. There are many complex processes happening behind the scenes, but the main logic remains unchanged.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So, as you can see, we have the ability to create any type of flow operator we can imagine using extension functions. Feel free to go crazy!&lt;/p&gt;

&lt;p&gt;To satisfy someone's curiosity, this is a Flow interface with a Generic type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Flow&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;suspend&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;collector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;FlowCollector&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;FlowCollector&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;suspend&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hope you understand why Flow is a simple yet powerful API implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;KotlinConf 2019: Asynchronous Data Streams with Kotlin Flow by Roman Elizarov:&lt;/strong&gt; &lt;a href="https://youtu.be/tYcqn48SMT8?si=4uo-G2Ryw4IQPYdS&amp;amp;t=1385"&gt;https://youtu.be/tYcqn48SMT8?si=4uo-G2Ryw4IQPYdS&amp;amp;t=1385&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Functional (SAM) interfaces:&lt;/strong&gt; &lt;a href="https://kotlinlang.org/docs/fun-interfaces.html"&gt;https://kotlinlang.org/docs/fun-interfaces.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kotlin extension function:&lt;/strong&gt; &lt;a href="https://kotlinlang.org/docs/extensions.html"&gt;https://kotlinlang.org/docs/extensions.html&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kotlin Generics:&lt;/strong&gt; &lt;a href="https://kotlinlang.org/docs/generics.html#variance"&gt;https://kotlinlang.org/docs/generics.html#variance&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kotlin</category>
      <category>flow</category>
      <category>android</category>
      <category>coroutine</category>
    </item>
    <item>
      <title>Using KSP output in app: Part 4</title>
      <dc:creator>Aniket Bhoite</dc:creator>
      <pubDate>Mon, 11 Apr 2022 06:07:12 +0000</pubDate>
      <link>https://dev.to/aniketbhoite/using-ksp-output-in-app-part-4-45il</link>
      <guid>https://dev.to/aniketbhoite/using-ksp-output-in-app-part-4-45il</guid>
      <description>&lt;p&gt;Now that we have our generated class, Let's try to use it in code.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Checkout other parts in this series:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Android KSP guide for dummies by a Dummy: Part 1 (&lt;a href="https://dev.to/aniketbhoite/android-ksp-guide-for-dummies-by-a-dummy-part-1-3dof"&gt;link&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;KSP Gradle setup &amp;amp; Processor's first log: Part 2 &lt;/li&gt;
&lt;li&gt;Generate the code using KSP : Part 3 (&lt;a href="https://dev.to/aniketbhoite/generate-the-code-using-ksp-part-3-223"&gt;link&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Using KSP output in app: Part 4&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;




&lt;p&gt;First let's look at what is Event Interface and what methods it contains.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.aniket.myevent

import android.os.Bundle

interface Event {
    fun getHashMapOfParamsForCustomAnalytics(): HashMap&amp;lt;*, *&amp;gt;?

    fun getBundleOfParamsForFirebase(): Bundle
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It means all generated Event classes must override both of the above-mentioned methods. &lt;/p&gt;

&lt;p&gt;We also need a Utility(helper) class that will use Event interface classes to fire events to respective analytics SDKs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.aniket.myevent

import android.util.Log

object EventUtils {

    fun postEvent(event: Event) {
        sendFirebaseEvent(event)
        sendCustomAnalyticEvent(event)
    }

    private fun sendFirebaseEvent(event: Event) {
        Log.i("Firebase_Event_fire", event.getBundleOfParamsForFirebase().toString())
    }

    private fun sendCustomAnalyticEvent(event: Event) {
        Log.i("Custom_Analytics_Event_fire", event.getHashMapOfParamsForCustomAnalytics().toString())
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default IDE is not aware the generated code. So it will mark references to generated symbols unresolvable. To make an IDE to aware about the generated codes we have to add following line in app(or consumer module)/build.gradle so IDE can import correct package names.&lt;/p&gt;

&lt;p&gt;Groovy Gradle&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// app/build/gradle

buildTypes {
    release {
        ....
        sourceSets {
            main {
                java { srcDirs = ["src", "build/generated/ksp/release/kotlin"]}
            }
        }
    }
    debug {
        ....
        sourceSets {
            main {
                java { srcDirs = ["src", "build/generated/ksp/debug/kotlin"]}
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kotlin Gradle&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// app/build.gradle.kts

buildTypes {
    getByName("release") {
        ....
        proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
        )
        sourceSets {
            getByName("main") {
                java.srcDir(File("build/generated/ksp/release/kotlin"))
            }
        }
    }
    getByName("debug") {
        ....
        sourceSets {
            getByName("main") {
                java.srcDir(File("build/generated/ksp/debug/kotlin"))
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Last thing do is actually trigger an Event&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bookTicketButton.setOnClickListener {
    EventUtils.postEvent(
        TicketBookClickedParamsEvent(
            TicketBookClickedParams(
                eventName = "TicketBookClicked",
                screenName = "MainActivity",
                ticketNumber = 1223,
                ticketAmount = "1220"
            )
        )
    )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's run the app and see fired events log&lt;/p&gt;

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

&lt;p&gt;Links&lt;br&gt;
GitHub repo part-4 branch: &lt;a href="https://github.com/aniketbhoite/ksp-my-event/tree/part-4" rel="noopener noreferrer"&gt;https://github.com/aniketbhoite/ksp-my-event/tree/part-4&lt;/a&gt;&lt;/p&gt;

</description>
      <category>android</category>
      <category>kotlin</category>
      <category>event</category>
      <category>metaprogramming</category>
    </item>
    <item>
      <title>Generate the code using KSP : Part 3</title>
      <dc:creator>Aniket Bhoite</dc:creator>
      <pubDate>Mon, 11 Apr 2022 06:06:31 +0000</pubDate>
      <link>https://dev.to/aniketbhoite/generate-the-code-using-ksp-part-3-223</link>
      <guid>https://dev.to/aniketbhoite/generate-the-code-using-ksp-part-3-223</guid>
      <description>&lt;p&gt;Good Morning, In this part let's start with understanding how processor gets called and how to use it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Checkout other parts in this series:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Android KSP guide for dummies by a Dummy: Part 1 (&lt;a href="https://dev.to/aniketbhoite/android-ksp-guide-for-dummies-by-a-dummy-part-1-3dof"&gt;link&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;KSP Gradle setup &amp;amp; Processor's first log: Part 2 (&lt;a href="https://dev.to/aniketbhoite/ksp-gradle-setup-processors-first-log-part-2-43b1"&gt;link&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Generate the code using KSP : Part 3&lt;/li&gt;
&lt;li&gt;Using KSP output in app: Part 4 (&lt;a href="https://dev.to/aniketbhoite/using-ksp-output-in-app-part-4-45il"&gt;link&lt;/a&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;




&lt;p&gt;Steps&lt;/p&gt;

&lt;h3&gt;
  
  
  1) Defining MyEvent annotation
&lt;/h3&gt;

&lt;p&gt;First lets define &lt;code&gt;MyEvent&lt;/code&gt; annotations class in annotations module&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.aniket.myevent.annotations

@Target(AnnotationTarget.CLASS)
annotation class MyEvent

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  2) Processing all Annotated classes in MyEventProcessor
&lt;/h3&gt;

&lt;p&gt;Registered Class &lt;code&gt;MyEventProcessorProvider&lt;/code&gt; which implements &lt;code&gt;SymbolProcessorProvider&lt;/code&gt; interface. We must override the &lt;u&gt;create&lt;/u&gt; method with SymbolProcessorEnvironment variable. In this method we have to initialise our &lt;code&gt;MyEventProcessor&lt;/code&gt; class with following variables(check part 2 point 4)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;environment.codeGenerator&lt;/code&gt;: helps with creating and managing files&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;environment.logger&lt;/code&gt;: for logging to build output.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;MyEventProcessor&lt;/code&gt; class implements &lt;code&gt;SymbolProcessor&lt;/code&gt; interface. We have to override abstract method &lt;u&gt;process(resolver: Resolver)&lt;/u&gt;. In this method we use resolver to get access to classes, functions or variables that are annotated with specified Annotation.&lt;/p&gt;

&lt;p&gt;Following code snippet we get us all class's with our Annotation i.e. MyEvent as KSAnnotated implantation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;val symbols = resolver
    .getSymbolsWithAnnotation(MyEvent::class.qualifiedName!!)
val unableToProcess = symbols.filterNot { it.validate() }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have to filter symbols because we only want symbols which are instance of &lt;code&gt;KSClassDeclaration&lt;/code&gt; and then we will visit each symbol one by one separately&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
val dependencies = Dependencies(false, *resolver.getAllFiles().toList().toTypedArray())

symbols.filter { it is KSClassDeclaration &amp;amp;&amp;amp; it.validate() }
    .forEach { it.accept(MyEventKClassVisitor(dependencies), Unit) }

return unableToProcess.toList()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In KSP we use Visitor Pattern, We will create &lt;code&gt;MyEventKClassVisitor&lt;/code&gt; inner class that implements &lt;code&gt;KSVisitorVoid()&lt;/code&gt; interface. Here we are only concerned with Classes so we will only override &lt;u&gt;visitClassDeclaration&lt;/u&gt; method.&lt;/p&gt;

&lt;p&gt;JavaTPoint website has very good easy explanation on visitor pattern, &lt;a href="https://www.javatpoint.com/visitor-design-pattern-java#:~:text=Visitor%20Pattern,operations%20from%20an%20object%20structure."&gt;click here to read&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private inner class MyEventKClassVisitor(val dependencies: Dependencies) : KSVisitorVoid() {

    override fun visitClassDeclaration(classDeclaration:             
        KSClassDeclaration, data: Unit) {
        ....
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before we go any further we need some validations that the classes that are annotated with &lt;code&gt;MyEvent&lt;/code&gt; are not Abstract or Interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (classDeclaration.isAbstract()) {
         logger.error(
          "||Class Annotated with MyEvent should kotlin data class",classDeclaration)
         }

if (classDeclaration.classKind != ClassKind.CLASS) {
       logger.error(
            "||Class Annotated with Projections should kotlin data class", classDeclaration)
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we need some variable strings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;val className = classDeclaration.simpleName.getShortName()
val classPackage = classDeclaration.packageName.asString() + "." + className
val classVariableNameInCamelCase = className.replaceFirst(className[0], className[0].lowercaseChar()) //need this for using in generated code

logger.warn("package $classPackage")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will also access that Class's primary constructor variables list&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;val properties = classDeclaration.primaryConstructor?.parameters ?: emptyList()

if (properties.isEmpty())
                logger.error("No variables found in class", classDeclaration)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tip: Use logger to understand and verify KSP variables.&lt;/p&gt;

&lt;p&gt;Now that we are on topic of properties lets add some helper Kotlin Extension function in processor module as below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
fun KSValueParameter.isNotKotlinPrimitive(): Boolean {

    return when (type.element?.toString()) {
        "String", "Int", "Short", "Number", "Boolean", "Byte", "Char", "Float", "Double", "Long", "Unit", "Any" -&amp;gt; false
        else -&amp;gt; true
    }
}

fun KSValueParameter.getPrimitiveTypeName(): String {

    return type.element?.toString() ?: throw IllegalAccessException()
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have access to all things we need for code generation.&lt;/p&gt;

&lt;p&gt;As per our requirement we need to generate 3 things&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Override Method &lt;u&gt;getBundleOfParamsForFirebase&lt;/u&gt; which returns Bundle with key values of event params&lt;/li&gt;
&lt;li&gt;Override Method &lt;u&gt;getHashMapOfParamsForCustomAnalytics&lt;/u&gt; which returns HashMap &lt;/li&gt;
&lt;li&gt;class that implements Event interface and holds above methods&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We need to add all parameters in hashmap and bundle in specific syntax.&lt;/p&gt;

&lt;p&gt;for Hashmap we need all properties like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hashmap.put("screenName",parmas.screenName)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;for bundle&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;putString("screenName", params.screenName)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will loop through all the properties and create their hash map and bundle entries in String builder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;val hashmapEntries = StringBuilder()
val bundleEntries = StringBuilder()
for (prop in properties) {
    // Throw Error if param is not primitive
    if (prop.isNotKotlinPrimitive())
        logger.error("|| Event params variables should be Primitive", prop)

    val propName = prop.name?.getShortName() ?: ""
    logger.warn("|| ${prop.name?.getShortName()}")

    hashmapEntries.append(
        """
                put("$propName", $classVariableNameInCamelCase.$propName)

                """.trimMargin()
    )

    val propPrimitiveTypeName = prop.getPrimitiveTypeName()

    bundleEntries.append(
        """
                put$propPrimitiveTypeName("$propName", $classVariableNameInCamelCase.$propName)

                """.trimMargin()
    )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we just have to generate Event class&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private val packageName = "com.aniket.myevent"

val toGenerateFileName = "${classDeclaration.simpleName.getShortName()}Event"

val outputStream: OutputStream = codeGenerator.createNewFile(
    dependencies = dependencies,
    packageName,
    fileName = toGenerateFileName
)



outputStream.write(
    """
    |package $packageName

    |import $classPackage
    |import android.os.Bundle
    |import $packageName.Event

    |class $toGenerateFileName(val $classVariableNameInCamelCase: $className): Event {
    |   override fun getHashMapOfParamsForCustomAnalytics(): HashMap&amp;lt;*, *&amp;gt;? {
    |       val map = HashMap&amp;lt;String, Any&amp;gt;().apply {
    |       $hashmapEntries
    |       }
    |       return map
    |    }
    |    
    |    override fun getBundleOfParamsForFirebase(): Bundle {
    |       val bundle = Bundle().apply {
    |       $bundleEntries
    |       }
    |       return bundle
    |    }
    |}
    """.trimMargin().toByteArray()
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Lets look at example of our usecase.&lt;/p&gt;

&lt;p&gt;For example with following class we ran or build app&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import com.aniket.myevent.annotations.MyEvent

@MyEvent
data class TicketBookToClickedParams(
    val eventName: String,
    val screenName: String,
    val ticketNumber: Int,
    val ticketAmount: String,
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The generated code of above Annotated class will be as follow at &lt;u&gt;&lt;em&gt;project/app/build/generated/ksp/debug/kotlin/com/aniket/myevent&lt;/em&gt;&lt;/u&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import android.os.Bundle

class TicketBookToClickedParamsEvent(val ticketBookToClickedParams: TicketBookToClickedParams) :
    Event {
    override fun getHashMapOfParamsForCustomAnalytics(): HashMap&amp;lt;*, *&amp;gt;? {
        val map = HashMap&amp;lt;String, Any&amp;gt;().apply {
            put("eventName", ticketBookToClickedParams.eventName)
            put("screenName", ticketBookToClickedParams.screenName)
            put("ticketNumber", ticketBookToClickedParams.ticketNumber)
            put("ticketAmount", ticketBookToClickedParams.ticketAmount)

        }
        return map
    }

    override fun getBundleOfParamsForFirebase(): Bundle {
        val bundle = Bundle().apply {
            putString("eventName", ticketBookToClickedParams.eventName)
            putString("screenName", ticketBookToClickedParams.screenName)
            putInt("ticketNumber", ticketBookToClickedParams.ticketNumber)
            putString("ticketAmount", ticketBookToClickedParams.ticketAmount)

        }
        return bundle
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point we are able generate Event class. Now the only thing remaining is Initialising and calling their methods to fire respective Events. We will do that in 4th and last part.  &lt;a href="https://dev.to/aniketbhoite/using-ksp-output-in-app-part-4-45il"&gt;Using KSP output in app: Part 4&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Links&lt;br&gt;
GitHub repo part-3 branch: &lt;a href="https://github.com/aniketbhoite/ksp-my-event/tree/part-3"&gt;https://github.com/aniketbhoite/ksp-my-event/tree/part-3&lt;/a&gt;&lt;/p&gt;

</description>
      <category>andorid</category>
      <category>ksp</category>
      <category>kotlin</category>
      <category>metaprogramming</category>
    </item>
    <item>
      <title>KSP Gradle setup &amp; Processor's first log: Part 2</title>
      <dc:creator>Aniket Bhoite</dc:creator>
      <pubDate>Mon, 11 Apr 2022 06:04:52 +0000</pubDate>
      <link>https://dev.to/aniketbhoite/ksp-gradle-setup-processors-first-log-part-2-43b1</link>
      <guid>https://dev.to/aniketbhoite/ksp-gradle-setup-processors-first-log-part-2-43b1</guid>
      <description>&lt;p&gt;In &lt;a href="https://dev.to/aniketbhoite/android-ksp-guide-for-dummies-by-a-dummy-part-1-3dof"&gt;first part&lt;/a&gt; we covered what KSP is and what problem we want solve using KSP. This part will cover setting up KSP in Android project with Groovy Gradle or new Kotlin DSL Gradle o Running KSP processor with first log&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Checkout other parts in this series:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Android KSP guide for dummies by a Dummy: Part 1 (&lt;a href="https://dev.to/aniketbhoite/android-ksp-guide-for-dummies-by-a-dummy-part-1-3dof"&gt;link&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;KSP Gradle setup &amp;amp; Processor's first log: Part 2 &lt;/li&gt;
&lt;li&gt;Generate the code using KSP : Part 3 (&lt;a href="https://dev.to/aniketbhoite/generate-the-code-using-ksp-part-3-223"&gt;link&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Using KSP output in app: Part 4 (&lt;a href="https://dev.to/aniketbhoite/using-ksp-output-in-app-part-4-45il"&gt;link&lt;/a&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;




&lt;p&gt;Steps&lt;/p&gt;

&lt;h3&gt;
  
  
  1) Adding JVM plugin in Project
&lt;/h3&gt;

&lt;p&gt;In project build gradle&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Different Kotlin DSL syntax is added in code block wherever needed&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//project/build.gradle

...
plugins {
    ...
    id "org.jetbrains.kotlin.jvm" version "1.6.10" apply false
}


//In kts.
/*
plugins {
    ...
    kotlin("jvm") version "1.6.10" apply false
}
*/

...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If project doesn’t have gradlePluginPortal() in plugin repositories then add it as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;repositories {
    gradlePluginPortal()
    ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  2) Creating Processor Module
&lt;/h3&gt;

&lt;p&gt;Create New module as java library named &lt;code&gt;processor&lt;/code&gt; to host symbol processor. Apply &lt;code&gt;java-library&lt;/code&gt;, &lt;code&gt;org.jetbrains.kotlin.jvm&lt;/code&gt; &amp;amp; &lt;code&gt;kotlin&lt;/code&gt; plugins in gradle with KSP's symbol processing api dependency. In processor's build.gradle&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//processor/build.gradle

plugins {
    id 'java-library'
    id 'org.jetbrains.kotlin.jvm'
    id 'kotlin'
}

//in Kts
/*
plugins {
    id("java-library")
    id("org.jetbrains.kotlin.jvm")
    id("kotlin")
}
*/

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

dependencies {
    implementation(project(":annotations"))
    implementation("com.google.devtools.ksp:symbol-processing-api:1.6.10-1.0.2")
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  3) Creating Annotations Module
&lt;/h3&gt;

&lt;p&gt;Create New module as java library named &lt;code&gt;annotations&lt;/code&gt; to define our custom annotations.&lt;/p&gt;

&lt;p&gt;annotations module's build.gradle&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//annotations/build.gradle

plugins {
    id 'java-library'
    id 'org.jetbrains.kotlin.jvm'
    id 'kotlin'
}

//in KTS
/*
plugins {
    id("java-library")
    id("org.jetbrains.kotlin.jvm")
    id("kotlin")
}
*/

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

dependencies {
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.10")
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  4) Creating Processor Classes
&lt;/h3&gt;

&lt;p&gt;Create &lt;code&gt;MyEventProcessor&lt;/code&gt; class&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.aniket.myevent.processor

...

class MyEventProcessor(
    private val codeGenerator: CodeGenerator,
    private val logger: KSPLogger,
    private val options: Map&amp;lt;String, String&amp;gt;
): SymbolProcessor {
    override fun process(resolver: Resolver): List&amp;lt;KSAnnotated&amp;gt; {

        logger.warn("Async Task API was very good API")
        return emptyList()
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create &lt;code&gt;MyEventProcessorProvider&lt;/code&gt; class&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.aniket.myevent.processor

...

class MyEventProcessorProvider: SymbolProcessorProvider {
    override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
        return MyEventProcessor(
            environment.codeGenerator,
            environment.logger,
            environment.options
        )
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Register your processor&lt;/strong&gt; in processor module&lt;br&gt;
&lt;code&gt;processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;as follows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;com.aniket.myevent.processor.MyEventProcessorProvider
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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




&lt;h3&gt;
  
  
  5) Applying KSP modules to app module
&lt;/h3&gt;

&lt;p&gt;Lets use annotation &amp;amp; processor module for KSP&lt;/p&gt;

&lt;p&gt;Add KSP plugin in the Project&lt;br&gt;
 project's build.gradle&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//project/build.gradle

buildscript {
    dependencies {
        ...
        classpath("com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:1.6.10-1.0.2")
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply KSP plugin, annotation module and processor module as KSP in app module&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//app/build.gradle


plugins {
    ...
    id 'com.google.devtools.ksp'
}

//in KTS
/*
plugins {
    ...
    id("com.google.devtools.ksp")
}
*/

dependencies {
    ...
    implementation(project(":annotations"))
    ksp(project(":processor"))
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: For now we are not writing any code in Annotation module, we will &lt;br&gt;
do that in future parts&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you want to run KSP in any other modules then same steps apply to that modules too&lt;/p&gt;

&lt;p&gt;Let's add Event Interface early so we can use that in future parts. You can add this interface in any package but make sure you use same the package name for Event interface in the code generation in future parts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.aniket.myevent

import android.os.Bundle

interface Event {
    fun getHashMapOfParamsForCustomAnalytics(): HashMap&amp;lt;*, *&amp;gt;?

    fun getBundleOfParamsForFirebase(): Bundle
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now Run app or build project and we can see our KSP log in build output&lt;/p&gt;

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

&lt;p&gt;Hooray!!!! You just added &amp;amp; ran your first KSP processor. Good job. Take a deep breath and go to sleep, KSP is not that important. GN&lt;/p&gt;

&lt;p&gt;In Next part, We will understand how KSP processor works and how to generate Code. &lt;a href="https://dev.to/aniketbhoite/generate-the-code-using-ksp-part-3-223"&gt;Generate the code using KSP : Part 3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Links&lt;br&gt;
GitHub repo part-2 branch: &lt;a href="https://github.com/aniketbhoite/ksp-my-event/tree/part-2" rel="noopener noreferrer"&gt;https://github.com/aniketbhoite/ksp-my-event/tree/part-2&lt;/a&gt;&lt;/p&gt;

</description>
      <category>android</category>
      <category>ksp</category>
      <category>gradle</category>
      <category>kotlin</category>
    </item>
    <item>
      <title>Android KSP guide for dummies by a Dummy: Part 1</title>
      <dc:creator>Aniket Bhoite</dc:creator>
      <pubDate>Mon, 11 Apr 2022 06:04:26 +0000</pubDate>
      <link>https://dev.to/aniketbhoite/android-ksp-guide-for-dummies-by-a-dummy-part-1-3dof</link>
      <guid>https://dev.to/aniketbhoite/android-ksp-guide-for-dummies-by-a-dummy-part-1-3dof</guid>
      <description>&lt;p&gt;KSP, Kotlin Symbol Processing is answer to annotation processing for Kotlin by &lt;a href="https://android-developers.googleblog.com/2021/02/announcing-kotlin-symbol-processing-ksp.html"&gt;google&lt;/a&gt;. It replaces older Kapt(Kotlin Annotations Processing) which was slower and less flexible to support native features of Kotlin language. &lt;/p&gt;

&lt;p&gt;KSP (or Kapt) is useful for meta-programming and writing repetitive code. We analyse code and use code to write code&lt;/p&gt;

&lt;h1&gt;
  
  
  Problem to solve
&lt;/h1&gt;

&lt;p&gt;To demonstrate let's take a problem to solve using KSP. In an average app there are maybe more than one analytic tools that requires event params in different formats. For example firebase Analytics SDK require params in key-value bundle but our own custom Analytic SDK accepts params in key-value pair HashMap&lt;/p&gt;

&lt;p&gt;For that we need to create class with two functions, one returning attributes in Bundle and 2nd in HashMap for every event&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    fun getBundleOfParamsForFirebase(): Bundle {
        val bundle = Bundle().apply {
            putString(paramName1, param1)
            putString(paramName2, param2)
        }
        return bundle
    }

    fun getHashMapOfParamsForCustomAnalytics(): HashMap&amp;lt;*, *&amp;gt;? {
        val map = HashMap&amp;lt;String, Any&amp;gt;().apply { 
            put(paramName1, param1)
            put(paramName1, param1)
        }
        return map
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks simple and doable manually but as number of params and number events increases it becomes cumbersome and error prone&lt;/p&gt;

&lt;p&gt;Let's look at a solution, in this we will only create  EventParams class with annotation based on which our Event class will get created. for ex.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @MyEvent
    data class TicketBookClickedParams(
        val eventName: String,
        val screenName: String,
        val ticketNumber: String,
        val ticketAmount: String
    )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;KSP processor will recognise all data classes Annotated with &lt;code&gt;@MyEvent&lt;/code&gt; annotation and generate Event class for it.&lt;/p&gt;

&lt;p&gt;This guide is further divided into parts, feel free to jump around if you like.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Intro&lt;/li&gt;
&lt;li&gt;KSP Gradle setup &amp;amp; Processor's first log: Part 2 (&lt;a href="https://dev.to/aniketbhoite/ksp-gradle-setup-processors-first-log-part-2-43b1"&gt;link&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Generate the code using KSP : Part 3 (&lt;a href="https://dev.to/aniketbhoite/generate-the-code-using-ksp-part-3-223"&gt;link&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Using KSP output in app: Part 4 (&lt;a href="https://dev.to/aniketbhoite/using-ksp-output-in-app-part-4-45il"&gt;link&lt;/a&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Title &amp;amp; disclaimer
&lt;/h1&gt;

&lt;p&gt;This series is for devs who have never used or created anything using KSP. This will not cover advance &amp;amp; complex use cases. This example will not have any kind of design pattern. We will go with straight forward approach which is not recommended for production apps. That’s why title is &lt;code&gt;guide for dummies by a Dummy&lt;/code&gt;(a or the Dummy depending upon whom you ask.)&lt;/p&gt;

&lt;p&gt;If anyone finds any mistakes or have any suggestion please feel free to add comment. &lt;/p&gt;

&lt;p&gt;Links: &lt;br&gt;
GitHub Repo : &lt;a href="https://github.com/aniketbhoite/ksp-my-event"&gt;https://github.com/aniketbhoite/ksp-my-event&lt;/a&gt;&lt;br&gt;
Google KSP Doc: &lt;a href="https://github.com/google/ksp"&gt;https://github.com/google/ksp&lt;/a&gt;&lt;br&gt;
KotlinLang KSP Doc: &lt;a href="https://kotlinlang.org/docs/ksp-overview.html"&gt;https://kotlinlang.org/docs/ksp-overview.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>android</category>
      <category>kotlin</category>
      <category>ksp</category>
      <category>metaprogramming</category>
    </item>
  </channel>
</rss>
