Categories
blog kotlin

SharedFlow

Intro

This is a third article in the series, please check out the other two articles here: 1st, 2nd

What is SharedFlow?

SharedFlow is a hot flow, it will emit data even though there are no observers/collectors. It’s important to mention this because everything will make more sense if this basic idea of hot vs cold flows/streams is understood. LiveData was a bit under-engineered in my option due to this fact, it was retrofitted to behave as both hot and cold stream, which did not work well and required some patching after the fact. 

When to use it?

It’s perfect for displaying one-off events like error messages and notifications to users. Since a hot flow will not re-emit values to new subscribers and it does not keep state, it’s impossible to display the same event twice. Although it can be customized, by default, it’s still a hot flow. 

When not to use it?

State management, since it does not keep any state SharedFlow is not suitable for state management, new subscribers won’t get the latest state. This can be tweaked also but by default, it does not work well for state management. 

SharedFlow vs Livedata

Those readers who used SingleLiveData or Event class with LiveData are familiar with hacks required to make LiveData behave like a hot flow. SharedFlow fills in that gap and makes it easy to handle one-off events like error messages. 

Nice to know SharedFlow APIs

With SharedFlow we can control how many last n events are played back to new subscribers, which is handy when we wanna maintain some state. extraBufferCapacity is handy when it comes to slow consumers, extra buffer capacity will let SharedFlow have additional items on top of the replayCache that helps slow subscribers get through all events

Categories
blog kotlin

StateFlow

Intro

If you need a refresher on hot vs cold flows check out the first article in the series

Hot flow

StateFlow is a hot flow and that means it will be alive and running even though subscriber count is zero. It’s very useful for state management since we want the state to be up to date even if no one is observing it so that when a new subscriber comes the latest, the correct state can be shown on the screen. Another nice feature of StateFlow is the .value parameter, it’s an easy and convenient way of reading the latest value without the need for launching coroutines.

Do we need a hot flow for state management?

If we think about the state of a screen and its logic, let’s say whether a user is signed in or not, does that state depend on an observer? Should it? It should not. If a user completes the sign-in flow, it does not matter if there was an observer to that event, we should be able to persist the fact that the user signed in. Otherwise, we would always need an observer to keep the state “correct, which is not ideal. That is why we need hot flow for state management, and we need the ability to broadcast the latest state to any new subscriber. 

Do we need StateFlow?

Can we just use regular Flow and let a flow handle app states? The problem with regular flows is that they are cold, they are not active if they don’t have any observers/subscribers. This is problematic since we want our state to be up to date and be available at all times. Regular flows are not a good use case for state management. StateFlow on the other hand is the opposite, it is a hot flow which means it will hold its value no matter if there are observers or not.

When to use it?

When we need to keep any kind of state and we want the last value to be accessible directly (through .value) StateFlow is idea for that

When not to use it?

In case we need something to behave like a cold flow. One good example of that is error events, we don’t want to keep errors and show them multiple times, ideally, we would show it only if there are observers and we don’t wanna keep errors stored because that would mean we could potentially show the same error multiple times. This was a common issue with LiveData, it needed a hack (SingleLiveData) in order to show an event only once. 

In the next article, we will explore the world of SharedFlow and how we can leverage it’s API

Categories
android blog kotlin

A basic comparison of LiveData, StateFlow, and SharedFlow

Why do we need these classes?

For one simple reason, reactivity. It’s very easy to keep the UI in sync when we don’t have to pull data from the View, instead, View is updated every time there is a change in the screen state. In a sense, this is an idea of unidirectional data flow. There is a single source of truth and everything is reacting to changes in the source. But we need more than that on mobile, we need to stop listening to updates when Views go out of scope to avoid null pointer exceptions. So we need a nice reactive pattern but we also need the ability to automatically unsubscribe from the updates if a particular Activity/Fragment is no longer visible. LiveData is essentially that. StateFlow and SharedFlow are different bests, and they are more like RxJava observables, (in Kotlin terms flow) but can be retrofitted to do the same thing.

Two fundamental types of streams 

If we step back and think about a stream of data, we fundamentally need two different cases, one where we want to grab every event and we don’t want the stream to start before we are ready, aka cold stream. The alternative to this is a hot stream, where we don’t care about consumers of the data, we are emitting values independently. It’s already clear which stream we would prefer for state and which for, let’s say error handling or one-off toast. StateFlow is a hot stream with the last value stored, any new subscriber will be immediately notified of the last value that a StateFlow emitted, making it ideal for keeping track of states in an app screen. Why is that the case? Well, we want to be able to always get the latest state for the screen so we can render the correct UI. Otherwise, we might render an outdated state, or we might be missing state till the next update comes. In contrast to that, let’s say we want to show an error message, we don’t wanna repeat the last error message every time we start listening for error messages. It makes sense to only display the same error message once.

Those are two fundamental use cases for mobile apps. So in a general sense, we are interested in hot streams, since we want to have the latest state processed regardless of the state of a particular Activity/Fragment.

LiveData is not enough

Didn’t we already have this with LiveData? It keeps the last value, it also updates its subscribers every time there is a new state, why do we need State or SharedFlow? Well, for starters LiveData was not suitable for errors and one-off message handling. In the end, a special Event data structure was needed to keep track of processed events. Another issue with LiveData is the lack of operators that it supports, operators like reply, debounce, filter, etc. It was a great solution for Android, but with StateFlow it kinda lost its place. StateFlow is an almost drop-in replacement for LiveData, and it’s supported with Kotlin out of the box. 

StateFlow

It can be called LiveData on steroids. It has similar properties in that it always has the last state saved but it also provides a rich API of operators. One shortcoming of StateFlow is that it does reply last event to new subscribers, which is ideal for state management, but not for one-off events. That is where SharedFlow comes in. 

StateFlow has a value property that can be read at any point in the life of a StateFlow, which is very handy when we need to access the latest state without subscribing. Because it has .value, StateFlow does require an initial value to be provided at the start. This is a bit cumbersome sometimes, but on the other hand, it’s nice to have null/nonnull .value property to be accessed at any point in the future.

Sharedflow

This is a hot flow that just emits values regardless of new subscribers. It can be configured to behave as StateFlow (practice question, how?) but in general, it does not have an initial value and it does not have .value property that can be accessed. By now, you should get a sense that SharedFlow is perfect for one-off events, where we don’t want to keep track of old states, we just wanna listen to new events and handle them as they go. 

Summary

So, how to pick a perfect Observable data structure for an Activity/Fragment? In simple terms, StateFlow is the default choice, if you get the feeling that there is a need for a one-off event, then SharedFlow is the way to go.

In the next couple of articles, we will go a bit more in-depth on StateFlow and SharedFlow. Happy coding!

Categories
blog productivity

Year 2020 – a review

So my goals for 2020 were pretty ambitious:

  1. Turn this blog into a quick reference site for Algorithms and Data structures (for my self and others)
    • Solve selected exercises from Elements of programming interviews book (Table 1.2 from the book)
    • Solve selected exercises from Data structures and algorithms made easy book
    • Due date: June 30
  2. Read Pragmatic programmer
    • Read all chapters and implement all exercises
    • Due date: March 30
  3. Read Deep work
    • Construct a work environment where deep work is easy and the only option
    • Due date: April 30
  4. Read clean architecture
    • Read all chapters and implement all exercises
    • Due date: April 30
  5. Port my Green to work app for iOS
    • Due date: November 30
  6. Read the War of art
    • Due date: May
  7. Publish 12 new articles, tech related:
    • Due date: December

So, what did I manage to accomplish? I did manage to read all the books and write 5 blog posts. So now that I am planning some goals for 2021 I wanna try and hit off the rest of the goals from 2020, which means at least 7 technical articles, and rewriting my green to work app to iOS. But instead of porting it to iOS I’ll focus on learning jetpack compose and rewrite it in compose.

I did not plan on starting a podcast in 2020, which I did. It’s called Hyperthread and it’s a tech podcast where I discuss various topics with my colleague Amel. After a couple of episodes it was clear that we are big Apple and Elon Musk fan boys :D. So, my plan for 2021 is pretty simple:

  • Publish 12 articles on my blog
  • Publish 12 podcasts
  • Rewrite green2work in jetpack compose and release it as an open source app
  • Read books on two topics: psychology and negotiation
  • Explore the world of espresso coffee
  • Attend Droidcon berlin

I am also playing around with an idea to have routines established for a typical work day, where I define my morning, work, evening routine. In general terms I wanna dedicate my morning routine to priming myself for the day, work routine should be focused on deep work, and evening routine is about unplugging and doing some analog activities. So thats what I’ll also work on during this year. Here is a break down of each routine

Morning:

  • Wake up, workout for 10 minutes
  • Read couple of pages from kindle
  • Journal for couple of minutes

Work:

  • No browsing
  • Work in pomodoro sessions

Evening:

  • Turn off my laptop 
  • Hide my phone away
  • Relax with light reading and journaling

Let’s go!

Categories
android blog kotlin

Building a podcast app series: 5. Dependency injection

Koin to the rescue

I am a big fan of dependency injection, I think no matter how small or big your application is, some sort of dependency injection is a must. Luckily there are multiple options to choose from when it comes to DI frameworks and my personal favorite is Koin.

If you are new to Koin or dependency injection, please check out my other blog series on Koin here.

In the context of our podcast app, Koin is responsible for creating and maintaining a single instance of ExoPlayer among other things, in fact, every object that we create and need to share its instance we will utilize Koin.

So how does Koin provide our ExoPlayer instance across the app? We will create an instance of ExoPlayer and wrap it around a single {} keyword (which is basically an infix extension function).

  single<ExoPlayer> {
    SimpleExoPlayer.Builder(androidContext()).build().apply {
            setAudioAttributes(
                AudioAttributes.Builder().setContentType(C.CONTENT_TYPE_MUSIC)
                    .setUsage(C.USAGE_MEDIA).build(), true
            )
            setHandleAudioBecomingNoisy(true)
        }
    }

single is a special Koin function that will make sure we are always injecting the same ExoPlayer instance in our app.

Now to inject this ExoPlayer instance we can use Kon’s inject or get extension methods to use lazy or eager injection. Here is the link to two Koin module files where we create all dependencies of our podcast app

With this its time to finish up our Building a podcast app blog series, I’ll see you again soon :).

Categories
android blog kotlin

Building a podcast app series: 4. Player service

How do we make sure that our app can run in the background and play a podcast without worrying about Android shutting the app down to claim resources? A foreground service to the rescue!

MediaBrowserServiceCompat

What the heck is a MediaBrowserServiceCompat? It’s a service that ExoPlayer ships with, and it can simplify the task of creating a background service for the player. Since Android O, any service that wants to be alive for extended periods of time should also show a notification and mark itself as a foreground service. To accomplish this we need to make use of PlayerNotificationManager class, also shipped with ExoPlayer, that given a media session token for our player will display a notification which will be in sync with the ExoPlayer. This is the most complicated part of the whole ExoPlayer setup because it works with a variety of Android APIs, and we all know how easy is it to use Android APIs.

PlayerNotificationManager

In order to utilize PlayerNotificationManager class, we need to create an instance of it and pass in a context, notification channel id, notification id, and a MediaDescriptionAdapter. The MediaDescriptionAdapter is how we tell the PlayerNotificationManager what is the title and image resource for our currently playing episode. Once we create an instance of this class, we can customize it in various ways. The most important method call after we create an instance is setPlayer(exoPlayerInstance). This is super important, given an ExoPlayer instance, PlayerNotificationManager will listen to that ExoPlayer instance changes and change the notification UI accordingly. This is a simple configuration of the PlayerNotificationManager

val playerNotificationManager = PlayerNotificationManager(context, channelId, notificationId, adapter)
playerNotificationManager.setPlayer(exoPlayer)
playerNotificationManager.setMediaSessionToken(it)

This leaves us with a question, who will supply an ExoPlayer instance? There can be a singleton that always returns a single instance, or even better, dependency injection can be used to provide the ExoPlyaer instance to different classes. That is what we will focus on the next, and it will be the last article in the series.

Notification channels

One thing we can do in this player service is to create a notification channel that PlayerNotificationManager will use to actually show a notification. Here is a simple way to create a new channel in case it is not created. Android O requires channels to be created before notifications can be presented to the user. We want to set the priority to low here to avoid any sounds or vibrations coming from the player notification when the user presses any action. Let’s look at an example

    private fun shouldCreateNowPlayingChannel(notificationManager: NotificationManagerCompat) =
        Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !nowPlayingChannelExists(
            notificationManager
        )

    @RequiresApi(Build.VERSION_CODES.O)
    private fun nowPlayingChannelExists(notificationManager: NotificationManagerCompat) =
        notificationManager.getNotificationChannel(nowPlayingChannelId) != null

    @RequiresApi(Build.VERSION_CODES.O)
    private fun createNowPlayingChannel(notificationManager: NotificationManagerCompat) {
        val notificationChannel = NotificationChannel(
            nowPlayingChannelId,
            getString(R.string.notification_channel),
            NotificationManager.IMPORTANCE_LOW
        ).apply {
           description = getString(R.string.notification_channel_description)
        }
         notificationManager.createNotificationChannel(notificationChannel)
    }

Checkout this Github link for the full player service code.

Stay tuned for the next article where we will explore a simple yet powerful dependency injection framework called Koin (technically it is a service locator but it enough to what we need for this app)

Categories
android blog kotlin

Building a podcast app series: 3. Exoplayer

What is a podcast app if not a wrapper around a media player? And, if we talk Android, there is the only one media player worth considering, ExoPlayer, made by Google engineers. Let’s look at how can we connect all the pieces we have built so far and actually connect the ExoPlayer with the view within the app.

ExoPlayer

Exoplayer is very powerful and modular, we are going to use just a fraction of what ExoPlayer really offers. ExoPlayer has a couple of core components that have to work together for it to play anything, in no particular order:

  1. ExoPlayer instance
  2. MediaSource

We need to create an ExoPlayer instance and hold it in memory since it is pretty expensive to create. We will reuse a single instance throughout the app. For it to play anything, we need to create a MediaSource. These sources are basically different types of streams that ExoPlayer has to read in order to fetch the audio data and play it. There are other important parts to the ExoPlayer ecosystem but for starters, we need those two basic things.

ExoPlayer instance

This is the heart of ExoPlayer and the object itself. We can simply create a single instance and pass or not pass a bunch of configuration options. Let’s keep it simple and create a basic instance:

val player = SimpleExoPlayer.Builder(context).build()

MediaSource

So the name of this class is pretty self-explanatory, we have to be aware of the fact that there are a couple of different media sources, depending on the actual source that serves the content:

  • DashMediaSource for DASH.
  • SsMediaSource for SmoothStreaming.
  • HlsMediaSource for HLS.
  • ProgressiveMediaSource for regular media files.

Let’s create a simple media source:

val mediaSource =
   ProgressiveMediaSource.Factory(dataSourceFactory).
        createMediaSource(Uri.parse(it.mp3Url))        
  exoPlayer.prepare(mediaSources)

And that’s it. We can now play an episode!

Since we are building a podcast player, it is safe to assume we will never play one episode at a time, so we need a way to tell ExoPlayer to play the next item when one item is finished playing. To handle that, ExoPlayer has a concept of the concatenated media source. We can bundle together a bunch of media sources, they don’t have to be of the same type, and attach that source to the ExoPlayer instance.

val mediaSources = (listOf(currentEpisode) + _playlist).map {
   ProgressiveMediaSource.Factory(dataSourceFactory).
        createMediaSource(Uri.parse(it.mp3Url))        
   }.toTypedArray()
exoPlayer.prepare(ConcatenatingMediaSource(*mediaSources)

So instead of passing just one media source, we can pass in a concatenating media source and the ExoPlayer will automatically play all episodes from that playlist.

Browse the full code on this link and in the next article, we will talk about a foreground service that needs to run our ExoPlayer and keep our app in the background so Android does not shut down our app to claim more resources :).

Categories
android architecture blog kotlin

Building a podcast app series: 2. Player state

After the view is set up, it’s very important to have a model that will drive that UI, something that we can observe and render our UI according to its state. It would be nice to react to model changes with some kind of a listener and it would be great if we don’t have to manually subscribe/unsubscribe to this model. Luckily, Android has a ViewModel class that is built for this exact purpose.

ViewModel

View modes are a relatively new invention. Before ViewModels came along, and the whole AAC (android architecture components), representing ViewModels in a clean and safe way was particularly tricky. Android activity or a fragment can be in multiple states and properly connecting/disconnecting a particular activity or a fragment is a dance around onCreate / onDestrory, onResume / onPause, and other lifecycle methods. Since our in-app player view is visible on all screens, wee need a globally accessible state holder for that player. Luckily, a ViewModel is all we need to safely share the player state across different fragments. Since we are using a single activity pattern, ViewModels are automatically tied to that activity and can be shared across fragments! This means that we can easily tell other views what is the state of our in-app player by just sharing a ViewModel across multiple fragments! Oh, by the way, ViewModels survive configuration change, so that is also being taken care of.

So, how do we create a new view model? We can simply write in any fragment

private val playerViewModel by sharedViewModel<PlayerViewModel>()

The basic idea here is that ViewModels do not care who is using its LiveData, it can be a single fragment or bunch of them, it does not matter. ViewModels should not reference any Fragment or Activity, they simply expose data for Views to observe!

If you are curious about the code for the PlayerViewModel check out this link.

LiveData

Once we have a shared state holder for our player, we need a safe way to update our views. That is where LiveData comes in, it is a safe container for any kind of data. And the best part about LiveData is that it automatically knows if our fragment or activity is active and can receive updates, so we don’t have to handle that logic ourselves! This means no more null pointer exceptions of illegal state exceptions. We are free to post new data to LiveData and be sure that nothing will crash as a result of that.

How do we create and update live data?

private val _currentlyPlaying = MutableLiveData<Episode>()
currentlyPlaying.value = currentEpisode

Repository pattern

The last piece of the state puzzle is to identify where does our data come from? In a simple word: from a Repository of Podcasts! Repository pattern is such a simple pattern and very useful. We can make our Repository do a bunch of interesting things. We can cache data to the local DB, we can mock our data, we can fetch something from the internet, everything related to data and its retrieval is hidden behind our Repository class.

How does a simple repository look like?

class PodcastRepository {
    fun getPodcasts(): List<Podcast> =
        listOf(Podcast("The Joe Rogan experience"))
}

Basic setup for every screen

In conclusion, every screen in our app will reference ViewModels and will subscribe to LiveDatas. ViewModels will fetch data from Repositories and update LiveDatas and we have a reactive setup for each screen in our app. Error handling is done in the same manner, we just have a LiveData of error messages where we can push errors and observe them inside Fragments.

Browse the full code on this link. Stay tuned for the next article in this series where we explore exoPlyaer, brains behind any podcast app.

Categories
android blog kotlin

Building a podcast app series: 1. mini in-app player

I am currently working on a project to rewrite an existing podcast app that was originally built with xamarin into a fully native Android app. The most important feature of any podcast app is the player, and specifically, the in-app player that has to:

  1. be visible on all screens
  2. have collapsed and expanded view

Let’s clarify the second point, the in-app player should have two modes, collapsed mode where the player’s view is small and should sit below the main content. The second mode is expanded mode, where the player’s view should occupy the whole screen. Ideally, there should be an animation when the player is transitioning between those two states. Let’s talk about solving problem number 1.

Navigation library

If we use the navigation library and single activity pattern from AAC (android architecture components), we can easily make our in-app player visible on all screens by restricting the navigation host fragment to be above the in-app player’s view. Since the navigation framework loads / unloads all views inside the navigation host fragment, we can make all views in our app span just up to the in-app player. If the player is hidden, all views automatically span over it, otherwise, they will span to just above the player.

A nice side effect of using the single activity pattern is the player itself will be configured from one place, main activity, and in combination with a view model, we can implement the player without violating the DRY principle. Now let’s talk about implementing the second feature.

Layout behavior

Ever since the coordinator layout came out, Android became a lot more flexible in terms of animations and interaction between views. In this specific use case all I had to do was to write a normal constraint layout and add one line to it:

<androidx.constraintlayout.widget.ConstraintLayout
....
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">

That was enough to have a view that can sit on the bottom of the screen, be expanded and animate those state changes out of the box. Pretty awesome if you ask me. So, how does the final layout look like?

<CoordinatorLayout>
   <MainContent/>
   <InAppPlayer/>
</CoordinatorLayout>

Of course, nothing is this simple, is it? :). But, what if our app has tabs and a BottomNavigationView? Our in-app player should, of course, sit above the BottomNavigationView but below the main content. One solution to this edge case is to position the main content above the bottom tabs’ view using constraint layout.

DRY principle and ViewModel

Since the player exists across multiple screens (fragments), we need a view model to group together all the player features in one place and just reuse the view model across all views. What better way to implement this than to use AAC ViewModel class. We can easily share this view model across fragments and have a player UI in sync at all times. PlayerViewModel can get data from a PodcastRepository class which will make network calls or read from the local database.

Please refer to this GitHub link for the code.

Stay tuned for the next article in this series!

Categories
productivity Uncategorized

2019 in a review and plan for 2020

At the beginning of this year, I started by writing a blog post about my goals for 2019. Looking at it now I realized how ambitious I was and how much time it would require to do all the things from the list. Something else I noticed is how little I changed my daily system to achieve those goals. I can confidently say that setting goals is not an optimal way of achieving something. That is why I am trying a different tactic this year. I will work on setting a new daily system instead of focusing on my goals for 2020. Of course, I will set some goals for 2020, but those goals will be of lesser importance than my daily workflow.

Goals vs Systems

So what is the big deal with systems? As with everything, boiling a thing down to its core elements can reveal quite a bit about the original thing. Setting goals is problematic in two fundamental ways:

  1. Goals are future-oriented and they are missing the crucial fast feedback loop
  2. Goals tell little on how to achieve them

So, to fix those two main issues the focus should be on systems instead of goals. This is one of those things that remains unnoticed until someone points it out. Everyone has a system that they follow in their daily life. The question is, is that the daily system set up in such a way that can help you achieve your goals? Most probably not, because goals require doing new things and that in turn requires acquiring new habits. Allocating time into a daily schedule is a crucial step in implementing the right system.

So, systems provide a solution to two major flows of setting goals outlined above. Firstly, systems are something that can be exercised daily, and the feedback loop is immediate. It’s as simple as asking a question, did I do 30 minutes of deep work on my new project today or not? If not, then I did not make any progress! The actual goal I am trying to achieve is hanging in the air. This feedback loop occurs every day and it’s a simple reminder that the actual goal I am perusing is not getting done any time soon. Another benefit of systems is that when we define a system to follow, we inherently have to come up with a plan on what behaviors will help in achieving that particular goal. For example, let’s say my goal in 2020 is to have a 10k mailing list. The goal itself does not mean anything unless we create a system around it to accomplish that. One such system is to set a time to write for 30 minutes, daily. That, in turn, requires changes to daily workflow. One could allocate that time right after work (and in doing that utilize a technique called habit stacking). Every day that those 30 minutes are skipped will be a reminder that the goal of 10k subscribers was just a wish on a piece of paper.

So, instead of plans for 2020, I will focus on systems and how to create a better system for myself. Currently, my system looks like this

  1. Wake up early, do some reading get inspired for the day
  2. Work 9 – 5
  3. Write a couple of paragraphs for my blog from 5 – 5:30
  4. Go home and rest

That’s it. That is my aim for 2020, a simple system to follow daily!