# Stojan Anastasov's blog

Android developer crafting native Android apps

This is one page of public article previews, not the complete archive. Follow Next page to continue. Summaries are not the original full articles.

## UI State, Callbacks and Equality Pitfalls

DevFeed: [UI State, Callbacks and Equality Pitfalls](<https://devfeed.tech/articles/ui-state-callbacks-and-equality-pitfalls-25875.md>)

Original publisher: [Read original article](<http://lordraydenmk.github.io//2024/ui-state-callbacks/>)

Author: Stojan Anastasov

Published: 2024-11-30T00:00:00Z

Content type: tutorial

Language: en

Sources: [Stojan Anastasov's blog](<https://devfeed.tech/sources/stojan-anastasov-s-blog.md>)

Topics: [ui](<https://devfeed.tech/topics/ui.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [Code](<https://devfeed.tech/topics/code.md>), [data](<https://devfeed.tech/topics/data.md>), [Compose](<https://devfeed.tech/topics/compose.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [code](<https://devfeed.tech/tags/code.md>), [data-class](<https://devfeed.tech/tags/data-class.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [pitfalls](<https://devfeed.tech/tags/pitfalls.md>), [sealed-class](<https://devfeed.tech/tags/sealed-class.md>), [state](<https://devfeed.tech/tags/state.md>), [ui](<https://devfeed.tech/tags/ui.md>)

### AI overview

This Kotlin article examines how callback functions embedded in UI state data classes can produce surprising equality results because function equality depends on reference identity. It explains the resulting update and performance issues in unidirectional data flow and discusses alternatives that keep action logic in the ViewModel or Presenter.

### Source excerpt

Yesterday a friend asked me to review his blog post on Function Properties in Data Classes are Code Smells. We then discussed how we would solve the issue in the context of UI state and callbacks. And I thought it might be useful to write it in form of a blog post. An example To better explain the problem, I'll start with a sample app I'm maintaining. It shows a list of superheroes from the Marvel API. See the screenshot below. Currently the UI state is modeled like: data class SuperheroViewEntity( val id: Long, val name: String, val imageUrl: HttpUrl ) Content( val superheroes: List<SuperheroViewEntity>, val copyright: String, ) // some states omitted for brevity A Naive Solution Let's say we have a new requirement, we want to add a favorite button to each superhero so we can keep track of our favorite superheroes. To do that we will introduce some functions: // ViewModel/Presenter fun onAddToFavorites(superheroId: Long) = TODO() fun onRemoveFromFavorites(superheroId: Long) = TODO() These functions can be part of the ViewModel/Presenter that delegates to a repository to store the IDs. Note: In this example, the ViewModel/Presenter use a single function per action the view can take. The technique described here also works with a single function + a sealed class for individual actions. To achieve this we might be tempted to update our SuperheroViewEntity to include: data class SuperheroViewEntity( val id: Long, val name: String, val imageUrl: HttpUrl, val onFavoriteClicked: () -> Unit ) // ViewModel fun Superhero.toViewEntity() = SuperheroViewEntity( id, name, imageUrl, if (favorite) { onRemoveFromFavorites(id) } else { onAddToFavorites(id) } ) // View layer Modifier.clickable { entity.onFavoriteClicked() } However this approach has some significant drawbacks. Functions in Kotlin are equal only if they are the same reference. val fa = { println(1) } val fb = { println(1) } println(fa == fb) // false, does the same job, but different reference val fc = fa println(fc =

## Modelling UI State on Android

DevFeed: [Modelling UI State on Android](<https://devfeed.tech/articles/modelling-ui-state-on-android-25873.md>)

Original publisher: [Read original article](<http://lordraydenmk.github.io//2021/modelling-ui-state/>)

Author: Stojan Anastasov

Published: 2021-01-29T00:00:00Z

Content type: tutorial

Language: en

Sources: [Stojan Anastasov's blog](<https://devfeed.tech/sources/stojan-anastasov-s-blog.md>)

Topics: [Android](<https://devfeed.tech/topics/android.md>), [android-development](<https://devfeed.tech/topics/android-development.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [Data structures](<https://devfeed.tech/topics/data-structures.md>), [Development](<https://devfeed.tech/topics/development.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [android-development](<https://devfeed.tech/tags/android-development.md>), [cardinality](<https://devfeed.tech/tags/cardinality.md>), [data-class](<https://devfeed.tech/tags/data-class.md>), [data-structure](<https://devfeed.tech/tags/data-structure.md>), [fp](<https://devfeed.tech/tags/fp.md>), [functional](<https://devfeed.tech/tags/functional.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [livedata](<https://devfeed.tech/tags/livedata.md>), [rxjava](<https://devfeed.tech/tags/rxjava.md>), [sealed-class](<https://devfeed.tech/tags/sealed-class.md>), [stateflow](<https://devfeed.tech/tags/stateflow.md>), [types](<https://devfeed.tech/tags/types.md>), [ui](<https://devfeed.tech/tags/ui.md>), [viewmodel](<https://devfeed.tech/tags/viewmodel.md>)

### AI overview

This article explains how to model Android UI state in Kotlin using data classes and sealed classes. It connects types with sets and cardinality, then describes product types and sum types as tools for representing valid application states.

### Source excerpt

The recommended approach from Google for Android development is holding the UI state in a ViewModel and having the View observe it. To achieve that one can use LiveData, StateFlow, RxJava or a similar tool. But how to model the UI state? Use a data class or a sealed class? Use one observable property or many? I will describe the tradeoffs between the approaches and present a tool to help you decide which one to use. This article is heavily inspired by Types as Sets from the Elm guide, a large part is a translation from Elm to Kotlin. Photo by Marc-Olivier Jodoin on Unsplash Types as sets By Making Data Structure we can make sure the possible values in code exactly match the valid values in real life. Doing that helps to avoid a whole class of bugs related to invalid data. To achieve that, first we need to understand the relationship between Types and Sets. We can think of Types as sets of values, they contain unique elements and there is no ordering between them. For example: Nothing - the empty set, it contains no elements Unit - the singleton set, it contains one element - Unit Boolean - contains the elements true and false Int - contains the elements: ... -2, -1, 0, 1, 2 ... Float - contains the elements: 0.1, 0.01, 1.0 .... String - contains the elements: "", "a", "b", "Kotlin", "Android", "Hello world!"... So when you write: val x: Boolean it means x belongs to the set of Boolean values and can be either true or false. Cardinality In Mathematics, Cardinality is the measure of "number of elements" of a Set. For example the set of Boolean contains the elements [true, false] so it has a cardinality = 2. Let's take a look at the cardinality of the sets mentioned above: Nothing - 0 Unit - 1 Boolean - 2 Short - 65535 Int - ∞ Float - ∞ String- ∞ Note: The cardinality of Int and Float is not exactly infinity, it's 2^32 however that is a huge number. When building apps, we use built-in types and create custom types using constructs like data classes and sealed classes. Product

## Unit Tests and Concurrency

DevFeed: [Unit Tests and Concurrency](<https://devfeed.tech/articles/unit-tests-and-concurrency-25874.md>)

Original publisher: [Read original article](<http://lordraydenmk.github.io//2021/unit-tests-and-concurrency/>)

Author: Stojan Anastasov

Published: 2021-01-06T00:00:00Z

Content type: tutorial

Language: en

Sources: [Stojan Anastasov's blog](<https://devfeed.tech/sources/stojan-anastasov-s-blog.md>)

Topics: [RxJava](<https://devfeed.tech/topics/rxjava.md>), [Concurrency](<https://devfeed.tech/topics/concurrency.md>), [Android](<https://devfeed.tech/topics/android.md>), [Testing](<https://devfeed.tech/topics/testing.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [api](<https://devfeed.tech/tags/api.md>), [concurrency](<https://devfeed.tech/tags/concurrency.md>), [junit](<https://devfeed.tech/tags/junit.md>), [observeon](<https://devfeed.tech/tags/observeon.md>), [recyclerview](<https://devfeed.tech/tags/recyclerview.md>), [rxjava](<https://devfeed.tech/tags/rxjava.md>), [scheduler](<https://devfeed.tech/tags/scheduler.md>), [testing](<https://devfeed.tech/tags/testing.md>), [tests](<https://devfeed.tech/tags/tests.md>), [trampoline](<https://devfeed.tech/tags/trampoline.md>)

### AI overview

This tutorial explains how replacing RxJava schedulers with a single test scheduler can hide concurrency problems. It presents an Android example involving concurrent API calls and discusses refactoring the RxJava chain to update the UI as results become available.

### Source excerpt

Once Retrofit added RxJava support, RxJava became my go-to concurrency framework for writing Android apps. One of the great things about RxJava is the excellent testing support. It includes TestObserver, TestScheduler, RxJavaPlugins so you can switch your schedulers in tests. A common approach in testing RxJava code is using a JUnit rule that replaces the Scheduler pools with Schedulers.trampoline() before tests are run and resets them to the original thread pools after the tests. This makes the whole Observable chain runs on a single thread, the same thread the test runs on, which means we can write assertions without worrying about concurrency. However the production code usually is not single threaded. IO operations are done on the IO thread pool, views are updated on the main thread and everything else happens on the computation pool. By using different schedulers in the tests and using a different strategy (single threaded) we make those unit tests useless in catching concurrency issues. A real world scenario I was working on a side project. The screen consists of a RecyclerView displaying a list of elements. To get the elements I need to perform two different API calls. The first API call returns a list with N elements, then for each item in the list I need to perform the second call. After combining the data I send it to the UI for displaying. Using RxJava this looks like: // Emits Loading then Content or Problem private fun requestData(): Observable<ViewState> = service.firstApiCall() .observeOn(Schedulers.computation()) .map { it.message } .flatMap(this::secondApiCall) .map<ViewState> { ViewState.Content(it) } .startWith(Single.just(ViewState.Loading)) .onErrorReturn { ViewState.Problem } .toObservable() // Concurrently executes secondApiCall for each element in list. // Transforms the result to ViewEntity, combines everything in a list private fun secondApiCall(list: List<String>): Single<List<ViewEntity>> = Observable.fromIterable(list) .concatMapEager {

## Fragments, ViewBinding and memory leaks

DevFeed: [Fragments, ViewBinding and memory leaks](<https://devfeed.tech/articles/fragments-viewbinding-and-memory-leaks-25871.md>)

Original publisher: [Read original article](<http://lordraydenmk.github.io//2020/view-binding/>)

Author: Stojan Anastasov

Published: 2020-10-30T00:00:00Z

Content type: tutorial

Language: en

Sources: [Stojan Anastasov's blog](<https://devfeed.tech/sources/stojan-anastasov-s-blog.md>)

Topics: [Android](<https://devfeed.tech/topics/android.md>), [Memory Leaks](<https://devfeed.tech/topics/memory-leaks.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [kotlin-android-extensions](<https://devfeed.tech/tags/kotlin-android-extensions.md>), [memory-leak](<https://devfeed.tech/tags/memory-leak.md>), [memory-leaks](<https://devfeed.tech/tags/memory-leaks.md>), [view-binding](<https://devfeed.tech/tags/view-binding.md>)

### AI overview

This article explains how Android view binding works with Kotlin and Java, focusing on the risk of memory leaks when a Fragment retains a binding after its view is destroyed. It argues that the issue results from placing the binding reference in the Fragment scope and recommends keeping it in a shorter-lived local function scope, particularly when using MVVM.

### Source excerpt

As an Android engineer one of the basic things you need to do is bind the views (written in XML) with Kotlin/Java code. You can do this with the basic primitive -findViewById(), using a library like ButterKnife, using a compiler plugin like Kotlin Android Extensions or starting with Android Studio/AGP 3.6 ViewBinding. There are a few other options out there but in my experience these are the most common. The Kotlin Android Extensions plugin will be deprecated (except the @Parcelize functionality) in favor of ViewBinding soon. I see this as a positive change, but not everyone shares my opinion. One of the common arguments against ViewBinding (according to a comment in the ticket, a discussion on reddit and a friend of mine) is: ViewBinding introduces memory leaks in Fragments. Let's take a look into the usage example from the official docs: private var _binding: ResultProfileBinding? = null // This property is only valid between onCreateView and // onDestroyView. private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { _binding = ResultProfileBinding.inflate(inflater, container, false) val view = binding.root return view } override fun onDestroyView() { super.onDestroyView() _binding = null } The fragment outlives the view, which means that if we forget to clear the binding reference in onDestroyView this will cause a memory leak. Now I do agree that this is error prone, you have to remember to clear the binding reference in each fragment you create. However this problem is not inherent to ViewBinding, but to this kind of usage. The problem here is: a component with a larger scope (the fragment) keeps a reference to a component with a smaller scope (the binding). Clearing the reference is a workaround, the proper solution is to move the reference to the correct scope: private val viewModel by viewModels<ProfileViewModel>() override fun onViewCreated(view: View, savedInsta

## Communicating with your Lifecycle Owner using RxJava

DevFeed: [Communicating with your Lifecycle Owner using RxJava](<https://devfeed.tech/articles/communicating-with-your-lifecycle-owner-using-rxjava-25872.md>)

Original publisher: [Read original article](<http://lordraydenmk.github.io//2020/viewmodel-lifecycle-owner-communication-rx/>)

Author: Stojan Anastasov

Published: 2020-09-08T00:00:00Z

Content type: tutorial

Language: en

Sources: [Stojan Anastasov's blog](<https://devfeed.tech/sources/stojan-anastasov-s-blog.md>)

Topics: [Android](<https://devfeed.tech/topics/android.md>), [Jetpack](<https://devfeed.tech/topics/jetpack.md>), [RxJava](<https://devfeed.tech/topics/rxjava.md>), [Coroutines](<https://devfeed.tech/topics/coroutines.md>), [Development](<https://devfeed.tech/topics/development.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [android-architecture](<https://devfeed.tech/tags/android-architecture.md>), [android-development](<https://devfeed.tech/tags/android-development.md>), [architecture](<https://devfeed.tech/tags/architecture.md>), [coroutines](<https://devfeed.tech/tags/coroutines.md>), [development](<https://devfeed.tech/tags/development.md>), [google](<https://devfeed.tech/tags/google.md>), [jetpack](<https://devfeed.tech/tags/jetpack.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [libraries](<https://devfeed.tech/tags/libraries.md>), [livedata](<https://devfeed.tech/tags/livedata.md>), [main-thread](<https://devfeed.tech/tags/main-thread.md>), [reactive](<https://devfeed.tech/tags/reactive.md>), [rxjava](<https://devfeed.tech/tags/rxjava.md>), [subscription](<https://devfeed.tech/tags/subscription.md>), [viewmodel](<https://devfeed.tech/tags/viewmodel.md>)

### AI overview

This tutorial explains LiveData in Android Jetpack, including lifecycle-aware observation, event handling, and use in the data layer. It compares LiveData with RxJava and Kotlin Flow, then describes a reactive RxJava approach for state observation and lifecycle-managed subscriptions.

### Source excerpt

Google introduced Jetpack, a family of opinionated libraries to make Android development easier a few years ago. One of the core classes in Jetpack is LiveData - an observable, lifecycle aware data holder. The typical use case is having a ViewModel that exposes LiveData as a property, and observing it from your lifecycle owner, a Fragment or an Activity. A typical usage would look like this: data class MyState(val value: String) class MyViewModel : ViewModel { private val _state = MutableLiveData<MyState>() val state: LiveData<MyState> get() = _state } class MyFragment : Fragment { val viewModel by viewModels<MyViewModel>() override fun onViewCreated() { viewModel.state.observe(this, Observer(::handleState)) } private fun handleState(state: MySate): Unit = TODO() } There are multiple benefits of using LiveData: Your observer is notified when the data changes The observer is only notified of changes when it's active Observers are notified when they become active again, like entering into foreground etc Check the LiveData docs for all benefits. LiveData and Events In situations like showing a Snackbar/dialog or navigating to a different Activity/Fragment the ViewModel also needs to notify the LifecycleOwner. A plain old LiveData doesn't work well here because it caches the last item. As a workaround, in the official Android architecture samples there is a SingleLiveEvent implementation of LiveData. Data Layer But what about the rest of the app? You can use LiveData in your data layer, in fact Room, the persistence library from Jetpack, support LiveData as the return type natively. However while using LiveData across all the layer in the app is possible, it is less than ideal. The operations are always executed on the Main Thread and it comes with limited number of transformation functions compared to RxJava or Flow. To fix this problem LiveData comes with adapters for both RxJava and Flow from KotlinX Coroutines. This means developers can use RxJava or Flow in their d

## Side Effects and Composition

DevFeed: [Side Effects and Composition](<https://devfeed.tech/articles/side-effects-and-composition-25870.md>)

Original publisher: [Read original article](<http://lordraydenmk.github.io//2019/side-effects-and-composition/>)

Author: Stojan Anastasov

Published: 2019-08-13T00:00:00Z

Content type: tutorial

Language: en

Sources: [Stojan Anastasov's blog](<https://devfeed.tech/sources/stojan-anastasov-s-blog.md>)

Topics: [Functional programming](<https://devfeed.tech/topics/functional-programming.md>), [Programming](<https://devfeed.tech/topics/programming.md>), [Code](<https://devfeed.tech/topics/code.md>), [Dependency injection](<https://devfeed.tech/topics/dependency-injection.md>), [SDKs](<https://devfeed.tech/topics/sdks.md>), [API](<https://devfeed.tech/topics/api.md>)

Tags: [api](<https://devfeed.tech/tags/api.md>), [arrowkt](<https://devfeed.tech/tags/arrowkt.md>), [code](<https://devfeed.tech/tags/code.md>), [dependency-injection](<https://devfeed.tech/tags/dependency-injection.md>), [fp](<https://devfeed.tech/tags/fp.md>), [functional](<https://devfeed.tech/tags/functional.md>), [functional-programming](<https://devfeed.tech/tags/functional-programming.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [programming](<https://devfeed.tech/tags/programming.md>)

### AI overview

This tutorial uses a coffee-shop payment example to explain side effects, testability, dependency injection, composition, and referential transparency in functional programming. It shows how extracting payment logic into a Payments object enables mock implementations for tests, and how reusing single-coffee logic for multiple coffees can avoid charging a credit card multiple times.

### Source excerpt

Photo by Ryan Yoo on Unsplash Functional Programing is amazing. It limits the things you can do (no nulls, no exceptions, no side effects...) and in return you get some benefits. Some benefits of FP are easy to explain and some not so much. I have been playing with FP for more than a year and only few weeks ago, when I started reading Functional Programming in Scala, I found an amazing example the benefits of pure functions. The problem Building a software for a Coffee Shop. For the initial MVP the requirements are: Sell coffee Pay with a card so the first draft of the code looks like this: import coffee.* fun buyCoffee(cc: CreditCard): Coffee { val cup = Coffee() cc.charge(cup.price) return cup } The buyCoffee function receives a CreditCard as an input and returns a Coffee as an output. It creates a Coffee object, then executes a charge and returns the Coffee object. Testability The call cc.charge uses an SDK/API to talk to the credit card company. It involves authorization, network call(s), persisting a record in the DB. The buyCoffee function returns a Coffee and the charging happens on the side hence the terms "side effect". The side effect makes buyCoffee hard to test in isolation. It would be nice (and cheaper) to run tests without actually talking to the credit card company and doing an actual charge. One could also argue that a CreditCard should not know how it's being charged. The testability problem can be fixed using Dependency Injection. fun buyCoffee(cc: CreditCard, p: Payments): Coffee { val cup = Coffee() p.charge(cc, cup.price) return cup } The logic of charging the credit card is extracted into the Payments object. In production code the real Payments implementation is used and a mock version is injected for tests. New requirements After a few weeks in business new requirements arrive. Some people buy more than one coffee so the next version of the software has additional requirements: Buying N coffees Single charge per Credit Card Composition The pro

## Functional Hangman in Kotlin with Arrow (part 2)

DevFeed: [Functional Hangman in Kotlin with Arrow (part 2)](<https://devfeed.tech/articles/functional-hangman-in-kotlin-with-arrow-part-2-25868.md>)

Original publisher: [Read original article](<http://lordraydenmk.github.io//2018/functional-hangman-in-kotlin-with-arrow-part-2/>)

Author: Stojan Anastasov

Published: 2018-12-25T00:00:00Z

Content type: tutorial

Language: en

Sources: [Stojan Anastasov's blog](<https://devfeed.tech/sources/stojan-anastasov-s-blog.md>)

Topics: [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [Programming](<https://devfeed.tech/topics/programming.md>), [IO](<https://devfeed.tech/topics/io.md>), [Error Handling](<https://devfeed.tech/topics/error-handling.md>)

Tags: [arrowkt](<https://devfeed.tech/tags/arrowkt.md>), [code](<https://devfeed.tech/tags/code.md>), [error-handling](<https://devfeed.tech/tags/error-handling.md>), [exception-handling](<https://devfeed.tech/tags/exception-handling.md>), [fp](<https://devfeed.tech/tags/fp.md>), [functional](<https://devfeed.tech/tags/functional.md>), [io](<https://devfeed.tech/tags/io.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>)

### AI overview

This tutorial explains the second part of converting a functional Hangman game from Scala with ZIO to Kotlin with Arrow. It replaces a hard-coded IO data type with a polymorphic design using Kind and introduces MonadDefer to represent capabilities such as lazy evaluation, exception handling, and completion with a result.

### Source excerpt

Converting a Functional Hangman game from Scala (ZIO) to Kotlin (with Arrow) was a nice exercise. I enjoyed working on it and I learned a lot. When I asked for feedback on the #arrow channel, one of the maintainers, Leandro had an interesting suggestion. Instead of hard-coding the data type IO I should try and make the program polymorphic and use Kind instead. That means writing the code focusing on the domain logic, using abstractions, and deferring the decision for the concrete data type like IO or Single (from RxJava) until the main function. The journey I was not familiar with that style of programming so I used this example from the excellent Arrow documentation as a guide. Writing to the the console In the previous article I used IO<A> to interact with the console. IO<A> represents an operation that can be executed lazily, fail with an exception (the exception is captured inside IO), run forever or return a single A. Let's take a look at the original implementation: fun putStrLn(line: String): IO<Unit> = IO { println(line) } // Usage in main() putStrLn("Hello world!").unsafeRunSync() putStrLn is a function that take a String and return a IO<Unit>. IO takes a lambda that is lazily evaluated at the end of the world, when we call unsafeRunSync(). If we want to achieve the same thing with Single we could use Single.fromCallable wrap our lambda and evaluate it in the main function when we call subscribe(). fun putStrLn(line: String): Single<Unit> = Single.fromCallable { println(line) } // Usage in main() putStrLn("Hello World").subscribe() Here bothIO and Single have something in common. A set of capabilities like: lazy evaluation, exception handling, and running forever or completing with a result of type A. IO and Single do a lot more, but for this use case, we want something as simple as possible that has the same capabilities. There is a type-class in Arrow that can do just that and it's called MonadDefer(more info). After a few iterations, and feedback from th

## Functional Hangman in Kotlin with Arrow

DevFeed: [Functional Hangman in Kotlin with Arrow](<https://devfeed.tech/articles/functional-hangman-in-kotlin-with-arrow-25869.md>)

Original publisher: [Read original article](<http://lordraydenmk.github.io//2018/functional-hangman-in-kotlin-with-arrow/>)

Author: Stojan Anastasov

Published: 2018-11-11T00:00:00Z

Content type: tutorial

Language: en

Sources: [Stojan Anastasov's blog](<https://devfeed.tech/sources/stojan-anastasov-s-blog.md>)

Topics: [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [Functional programming](<https://devfeed.tech/topics/functional-programming.md>), [IO](<https://devfeed.tech/topics/io.md>), [Scala](<https://devfeed.tech/topics/scala.md>), [Coroutines](<https://devfeed.tech/topics/coroutines.md>), [Code](<https://devfeed.tech/topics/code.md>)

Tags: [arrowkt](<https://devfeed.tech/tags/arrowkt.md>), [code](<https://devfeed.tech/tags/code.md>), [coroutines](<https://devfeed.tech/tags/coroutines.md>), [fp](<https://devfeed.tech/tags/fp.md>), [functional-programming](<https://devfeed.tech/tags/functional-programming.md>), [io](<https://devfeed.tech/tags/io.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [programming](<https://devfeed.tech/tags/programming.md>), [scala](<https://devfeed.tech/tags/scala.md>)

### AI overview

A developer describes rewriting a functional console Hangman game from Scala ZIO in Kotlin with Arrow. The article compares their IO abstractions, console I/O, and approaches to for-comprehension-like code, noting that the implementations are not fully equivalent.

### Source excerpt

A few days ago I run into this blog post about implementing a console Hangman game using Scala ZIO. The blog post is based on this talk delivered by John De Goes, for the Scala Kyiv meetup, where he codes a console Hangman game using functional programming. After I saw the post I was curious how the code would look like written in Koltin with arrow so I decided to try and write it. You can find the result here. I am still learning functional programming so I asked for feedback from the arrow maintainers on the kotlinlang slack workspace. They were very helpful and I made a few improvements based on their feedback. Key differences I would like to point out that the programs in Scala and Kotlin are not 100% equivalent. There are both differences in the language and the functional libraries used. The IO monad In Scala ZIO IO[E, A] describes an effect that may fail with an E, run forever, or produce a single A. In the Kotlin version I am using IO<A> from Arrow. IO<A> describes an effect that can fail with Throwable or produce a single A. Both type classes produce an A. The key difference the error. In Scala ZIO you can use any error type or even Nothing to indicate the program never ends. In Arrow the E type is always Throwable so you don't have to specify it. Reading and writing from the Console Scala ZIO comes with built in primitives for interacting with the console. In the Kotlin version I had to implement the readStrLn and putStrLn functions myself. 1 2 3 4 5 fun putStrLn(line: String): IO<Unit> = IO { println(line) } fun getStrLn(): IO<String> = IO { readLine() ?: throw IOException("Failed to read input!") } For comprehensions For comprehensions are built into the scala language. Unfortunately Kotlin doesn't have the same feature. But Kotlin has Coroutines so the Arrow team built Comprehensions over coroutines which can be used in a similar way to make the code more readable. 1 2 3 4 5 6 7 8 9 10 //Scala with For comprehensions val hangman : IO[IOException, Unit]

## Setting up GitLab CI for Android Projects

DevFeed: [Setting up GitLab CI for Android Projects](<https://devfeed.tech/articles/setting-up-gitlab-ci-for-android-projects-25867.md>)

Original publisher: [Read original article](<http://lordraydenmk.github.io//2017/setting-up-gitlab-ci-for-android/>)

Author: Stojan Anastasov

Published: 2017-12-03T00:00:00Z

Content type: tutorial

Language: en

Sources: [Stojan Anastasov's blog](<https://devfeed.tech/sources/stojan-anastasov-s-blog.md>)

Topics: [GitLab](<https://devfeed.tech/topics/gitlab.md>), [Android](<https://devfeed.tech/topics/android.md>), [ci](<https://devfeed.tech/topics/ci.md>), [SDK](<https://devfeed.tech/topics/sdk.md>), [Command-line interface](<https://devfeed.tech/topics/cli.md>), [Testing](<https://devfeed.tech/topics/testing.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [android-testing](<https://devfeed.tech/tags/android-testing.md>), [androiddev](<https://devfeed.tech/tags/androiddev.md>), [command-line](<https://devfeed.tech/tags/command-line.md>), [continuous-integration](<https://devfeed.tech/tags/continuous-integration.md>), [gitlab](<https://devfeed.tech/tags/gitlab.md>), [gitlab-ci](<https://devfeed.tech/tags/gitlab-ci.md>), [sdk](<https://devfeed.tech/tags/sdk.md>), [unit-testing](<https://devfeed.tech/tags/unit-testing.md>)

### AI overview

A tutorial for configuring GitLab CI for Android projects. It explains installing Android command-line tools and SDK packages, transferring accepted licenses to a CI server, and handling emulator limitations when running functional tests.

### Source excerpt

My first experience with continuous integration was using Bitbucket in combination with Jenkins. I was pretty happy with my setup. Jenkins would run on every commit making sure my code compiles, run android lint and run my unit tests. I also set up continuous deployment using Fabric. Now, at work, we use GitLab as a code repository. GitLab also offers continuous integration. When we decided to start using continuous integration at work we decided to give GitLab a chance. It was already integrated with GitLab and to use it we just needed to install a runner. Using CI with GitLab is simple, after you install a runner you need to add a .gitlab-ci.yml file at the root of the repository. GitLab even offers template .gitlab-ci.yml files for various languages and frameworks. The android template is based on this blog post from 2016. It is a great guide but unfortunately today it doesn't work. Google introduced a few changes in the command line tools. Installing Android SDK To install the Android SDK on a CI we need to install the command line tools (scroll to the bottom to Get just the command line tools). The command line tools include the sdkmanager - a command line tool that allows you to view, install, update, and uninstall packages for the Android SDK. So instead of - wget --quiet --output-document=android-sdk.tgz https://dl.google.com/android/android-sdk_r${ANDROID_SDK_TOOLS}-linux.tgz - tar --extract --gzip --file=android-sdk.tgz we can use - wget --quiet --output-document=android-sdk.zip https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip - unzip -q android-sdk.zip -d android-sdk-linux to download and install the Android SDK tools. There is also an improvement in accepting licenses for the Android SDK. After you accept the licenses on your development machine the tools will generate a licenses folder in the Android SDK root directory. You can transfer the licenses from your development machine to your CI server. To accept the licenses we can use: -

## Contributing to OSS for Hacktoberfest

DevFeed: [Contributing to OSS for Hacktoberfest](<https://devfeed.tech/articles/contributing-to-oss-for-hacktoberfest-25866.md>)

Original publisher: [Read original article](<http://lordraydenmk.github.io//2017/contributing-to-oss-for-hacktoberfest/>)

Author: Stojan Anastasov

Published: 2017-10-10T00:00:00Z

Content type: opinion

Language: en

Sources: [Stojan Anastasov's blog](<https://devfeed.tech/sources/stojan-anastasov-s-blog.md>)

Topics: [Hacktoberfest](<https://devfeed.tech/topics/hacktoberfest.md>), [pull-requests](<https://devfeed.tech/topics/pull-requests.md>), [GitHub](<https://devfeed.tech/topics/github.md>), [JavaFX](<https://devfeed.tech/topics/javafx.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [bug](<https://devfeed.tech/tags/bug.md>), [development](<https://devfeed.tech/tags/development.md>), [github](<https://devfeed.tech/tags/github.md>), [hacktoberfest](<https://devfeed.tech/tags/hacktoberfest.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [library](<https://devfeed.tech/tags/library.md>), [open-source](<https://devfeed.tech/tags/open-source.md>), [oss](<https://devfeed.tech/tags/oss.md>), [pull-request](<https://devfeed.tech/tags/pull-request.md>), [pull-requests](<https://devfeed.tech/tags/pull-requests.md>), [unit-tests](<https://devfeed.tech/tags/unit-tests.md>)

### AI overview

A personal account of contributing to open-source projects during Hacktoberfest 2017. The author describes fixing an outdated dependency reference and a documentation-related bug, then adding unit tests and fixing another bug in TornadoFx, a JavaFX framework for Kotlin.

### Source excerpt

Digital Ocean in partnership with Github are organizing the fourth Hacktoberfest event this October. If you make four pull requests between October 1 and October 31 to any Github hosted repository you get a Hacktoberfest T-shirt. This year I decided to take part and I already made two pull requests. My first OSS contribution I created my first pull request to an OSS project 3 years after I registered on Github. I know it can be hard to start contributing. At first I didn't think my code was good enough, then I couldn't find the right project with the right issue I could fix. One day an opportunity presented itself. At work I was using auto-parcel to generate the boilerplate required for Parcebale implementation on Android. It's a cool library based on auto-value by Google. At the time I was using version 0.3 - the version displayed in the README file on Github. A few days later while creating another value class I got an error. I googled the error and it led me to an issue on the project's Github page. The issue was closed and a new version, version 0.3.1 was released. The README file was outdated, it still pointed to the previous release containing the bug. I spent 10 minutes because of a bug that was already fixed. What a waste of time. If I wasted time chances are someone else will also run into the same problem so I decided to do something about it. Opening an issue on Github would be nice but the solution was so simple I decided to fix it myself and make a pull request. I also updated another dependency (android-apt) in the README to the latest version. The next day my pull request was accepted and it felt good. Hacktoberfest 2017 A few days after Hacktoberfest 2017 started I run into an interested project on Github - TornadoFx a Lightweight JavaFX framework for Kotlin. I like Kotlin and it's Hacktoberfest so I decided to contribute and maybe get a cool T-Shirt in the process. I noticed the project didn't have enough unit tests so I decided to write a few. I fo