If you’re an Android developer and want to build applications asynchronously, you might want to use RxJava, because RxJava has operators that can be used for almost any operation and has become one of the most important pieces of knowledge in Android.

However, with Kotlin, many people start to prefer coroutines. Jetbrains ships with the Flow API in Kotlin Coroutine 1.2.0 alpha. Now, with the help of the Flow API in Kotlin, you can process the sequential Flow of data.

In Kotlin, Coroutine is just the scheduler part of RxJava but now with Flow APIs coming along side it, it can be alternative to RxJava in Android.

Flow with coroutines can replace Rxjava in Android.

In this blog, we’ll learn how the Flow API works in Kotlin and how to use it in our Android project. This article will cover the following topics:

  • What is the Flow API in Kotlin coroutines?

  • Start integrating the Flow API into your projects

  • Flow builder

  • Some examples use the Flow operator

This article will discuss them all.

What is the Flow API in Kotlin coroutines?

The Flow API in Kotlin is a better way to handle sequential data flows asynchronously.

In RxJava, the Observables type is an example of representing the structure of a project flow. The principal is not executed until the subscriber subscribes. After subscribing, the subscriber starts retrieving the transmitted data items. Again, Flow works under the same condition that the code inside the Flow generator does not run until it reaches the collection Flow.

Start integrating the Flow API into your projects

Let’s create an Android project and integrate the Kotlin Flow API.

The first step

Add the following to your application’s build.gradle

implementation "Org. Jetbrains. Kotlinx: kotlinx coroutines -- core: 1.3.3." "
implementation "Org. Jetbrains. Kotlinx: kotlinx coroutines - android: 1.3.3." "
Copy the code

Add it to build.gradle in your project

implementation "Org. Jetbrains. Kotlinx: kotlinx coroutines -- core: 1.3.3." "
implementation "Org. Jetbrains. Kotlinx: kotlinx coroutines - android: 1.3.3." "
Copy the code
The second step

In the MainActivity layout file, we create a UI page with buttons.

<?xml version="1.0" encoding="utf-8"? >
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        android:text="Launch Kotlin Flow"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code
The third step

Now, let’s start implementing the Flow API in MainActivity. In the Activity’s onCreate () function, we can add two functions, for example:

override fun onCreate(savedInstanceState: Bundle?). {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    setupFlow()
    setupClicks()
}
Copy the code

We will declare a Flow lateinit variable of type Int:

lateinit var flow: Flow<Int>
Copy the code
The fourth step

Write code in setupFlow () to emit data items every 500 milliseconds.

fun setupFlow(a){
    flow = flow {
        Log.d(TAG, "Start flow")
        (0.10.).forEach {
            // Emit items with 500 milliseconds delay
            delay(500)
            Log.d(TAG, "Emitting $it")
            emit(it)

        }
    }.flowOn(Dispatchers.Default)
}
Copy the code

About here:

  • We will emit numbers from 0 to 10 with a delay of 500ms.
  • To emit data, we will use **emit()** to collect emitted values. It is aFlowCollectorCan be used as a receiver.
  • Finally, we use the flowOn operator, which means you should use it to change the context in which the flow is emitted. Here, we can use different dispatchers such as IO, Default, etc.

FlowOn () is just like subscribeOn() in RxJava

Step 5

Now we need to write the **setupClicks () ** function, where we need to print the value emitted from the stream.

private fun setupClicks(a) {
    button.setOnClickListener {
        CoroutineScope(Dispatchers.Main).launch {
            flow.collect {
                Log.d(TAG, it.toString())
            }
        }
    }
}
Copy the code

When we click the button, we print the values one by one.

Explain:

  • Flow.collect will now start extracting/collecting values from the stream on the main thread.
  • The UI will look something like this:

  • The output is as follows:
D/MainActivity: Start flow
D/MainActivity: Emitting 0
D/MainActivity: 0
D/MainActivity: Emitting 1
D/MainActivity: 1
D/MainActivity: Emitting 2
D/MainActivity: 2
D/MainActivity: Emitting 3
D/MainActivity: 3
D/MainActivity: Emitting 4
D/MainActivity: 4
D/MainActivity: Emitting 5
D/MainActivity: 5
D/MainActivity: Emitting 6
D/MainActivity: 6
D/MainActivity: Emitting 7
D/MainActivity: 7
D/MainActivity: Emitting 8
D/MainActivity: 8
D/MainActivity: Emitting 9
D/MainActivity: 9
D/MainActivity: Emitting 10
D/MainActivity: 10
Copy the code

As you can see, the Flow only starts when the button is clicked, because it prints “Start Flow” and then starts firing.

Suppose we modify the **setupFlow () ** function

private fun setupFlow(a) {
    flow = flow {
        Log.d(TAG, "Start flow")
        (0.10.).forEach {
            // Emit items with 500 milliseconds delay
            delay(500)
            Log.d(TAG, "Emitting $it")
            emit(it)
        }
    }.map {
        it * it
    }.flowOn(Dispatchers.Default)
}
Copy the code

Here, you can see that we have added the Map operator, which will take each value, square itself and print it out.

Everything written on flowOn will run in the background thread.

Flow builder

A flow builder is nothing more than a way to build a flow. There are 4 ways:

  • FlowOf () – To create a flow from a given set of values. Such as:
flowOf(4.2.5.1.7).onEach { delay(400) }.flowOn(Dispatcher.Default)

Copy the code

Here, the **flowOf () ** takes a fixed value and prints each fixed value every 400 milliseconds. When we attach the collector to the stream, we get output:

D/MainActivity: 4
D/MainActivity: 2
D/MainActivity: 5
D/MainActivity: 1
D/MainActivity: 7
Copy the code
  • AsFlow () – This is an extension to help convert types to flows. Such as:
(1.. 5).asFlow().onEach{ delay(300)}.flowOn(Dispatchers.Default)
Copy the code

Here, we convert data ranging from 1 to 5 as streams and transmit each of them with a delay of 300 milliseconds. When we attach the collector to the stream, we get the following output:

D/MainActivity: 1
D/MainActivity: 2
D/MainActivity: 3
D/MainActivity: 4
D/MainActivity: 5
Copy the code
  • Flow {}- This example is illustrated in the Android example above. This is a constructor used to construct any flow.

  • ChannelFlow {}- This builder creates a cold flow using the send and elements provided by the builder itself. Such as:

channelFlow {
    (0.10.).forEach {
        send(it)
    }
}.flowOn(Dispatchers.Default)
Copy the code

The output is as follows:

D/MainActivity: 0
D/MainActivity: 1
D/MainActivity: 2
D/MainActivity: 3
D/MainActivity: 4
D/MainActivity: 5
D/MainActivity: 6
D/MainActivity: 7
D/MainActivity: 8
D/MainActivity: 9
D/MainActivity: 10

Copy the code

Finally, let’s look at how to use the Flow operator in a project.

Zip operator.

If you remember from the example above, we have two methods, setupFlow () and setupClicks (). We will modify both functions in MainActivity.

First, we will declare two lateInit variables of type String Flow,

lateinit var flowOne: Flow<String>
lateinit var flowTwo: Flow<String>
Copy the code

Then in setupFlow (), the two flows are initialized as two variables.

private fun setupFlow(a) {
    flowOne = flowOf("Himanshu"."Amit"."Janishar").flowOn(Dispatchers.Default)
    flowTwo = flowOf("Singh"."Shekhar"."Ali").flowOn(Dispatchers.Default)

}
Copy the code

In setupClicks (), we use the ZIP operator to compress the two streams.

private fun setupClicks(a) {
    button.setOnClickListener {
        CoroutineScope(Dispatchers.Main).launch {
            flowOne.zip(flowTwo)
            { firstString, secondString ->
                "$firstString $secondString"
            }.collect {
                Log.d(TAG, it)
            }
        }
    }
}
Copy the code

To clarify:

  • When the button is clicked, execution begins.
  • Compressing flowOne and flowTwo produces a pair of data, firstString and secondString, which we concatenate.
  • And then print it out in Logcat. The resulting output would be:
D/MainActivity: Himanshu Singh
D/MainActivity: Amit Shekhar
D/MainActivity: Janishar Ali
Copy the code

Note: If two streams do not have the same number of items, the stream will stop as soon as one of them completes.

To view items, click here

By Team MindOrks 🙂

Original link: blog.mindorks.com/what-is-flo…

==================== split line ======================

If you want to learn more about MVVM, Flutter, and responsive programming, please follow me.

You can find me at:

Jane: www.jianshu.com/u/117f1cf0c…

The Denver nuggets: juejin. Cn/user / 817692…

Github: github.com/ditclear