Where to do Arrow.io IO.runUnsafeSync() ? ViewModel or Activity/Fragment? - android

I'm trying to learn the Arrow library and improve my functional programming by transitioning some of my Android Kotlin code from more imperative style to functional style. I've been doing a type of MVI programming in the application to make testing simpler.
"Traditional" Method
ViewModel
My view model has a LiveData of the view's state plus a public method to pass user interactions from the view to the viewmodel so the view model can update state in whatever way is appropriate.
class MyViewModel: ViewModel() {
val state = MutableLiveData(MyViewState()) // MyViewState is a data class with relevant data
fun instruct(intent: MyIntent) { // MyIntent is a sealed class of data classes representing user interactions
return when(intent) {
is FirstIntent -> return viewModelScope.launch(Dispatchers.IO) {
val result = myRoomRepository.suspendFunctionManipulatingDatabase(intent.myVal)
updateStateWithResult(result)
}.run { Unit }
is SecondIntent -> return updateStateWithResult(intent.myVal)
}
}
}
Activity
The Activity subscribes to the LiveData and, on changes to state, it runs a render function using the state. The activity also passes user interactions to the view model as intents (not to be confused with Android's Intent class).
class MyActivity: AppCompatActivity() {
private val viewModel = MyViewModel()
override fun onCreateView() {
viewModel.state.observe(this, Observer { render(it) })
myWidget.onClickObserver = {
viewModel.instruct(someIntent)
}
}
private fun render(state: MyViewState) { /* update view with state */ }
}
Arrow.IO Functional Programming
I'm having trouble finding examples that aren't way over my head using Arrow's IO monad to make impure functions with side effects obvious and unit-testable.
View Model
So far I have turned my view model into:
class MyViewModel: ViewModel() {
// ...
fun instruct(intent: MyIntent): IO<Unit> {
return when(intent) {
is FirstIntent -> IO.fx {
val (result) = effect { myRoomRepository.suspendFunctionManipulatingDatabase(intent.myVal) }
updateStateWithResult(result)
}
is SecondIntent -> IO { updateStateWithResult(intent.myVal) }
}
}
}
I do not know how I am supposed to make this IO stuff run in Dispatcher.IO like I've been doing with viewModelScope.launch. I can't find an example for how to do this with Arrow. The ones that make API calls all seem to be something other than Android apps, so there is no guidance about Android UI vs IO threads.
View model unit test
Now, because one benefit I'm seeing to this is that when I write my view model's unit tests, I can have a test. If I mock the repository in order to check whether suspendFunctionManipulatingDatabase is called with the expected parameter.
#Test
fun myTest() {
val result: IO<Unit> = viewModel.instruct(someIntent)
result.unsafeRunSync()
// verify suspendFunctionManipulatingDatabase argument was as expected
}
Activity
I do not know how to incorporate the above into my Activity.
class MyActivity: AppCompatActivity() {
private val viewModel = MyViewModel()
override fun onCreateView() {
viewModel.state.observe(this, Observer { render(it) })
myWidget.onClickObserver = {
viewModel.instruct(someIntent).unsafeRunSync() // Is this how I should do it?
}
}
// ...
}
My understanding is anything in an IO block does not run right away (i.e., it's lazy). You have to call attempt() or unsafeRunSync() to get the contents to be evaluated.
Calling viewModel.instruct from Activity means I need to create some scope and invoke in Dispatchers.IO right? Is this Bad(TM)? I was able to confine coroutines completely to the view model using the "traditional" method.
Where do I incorporate Dispatchers.IO to replicate what I did with viewModelScope.launch(Dispatchers.IO)?
Is this the way you're supposed to structure a unit test when using Arrow's IO?

That's a really good post to read indeed. I'd also recommend digging into this sample app I wrote that is using ArrowFx also.
https://github.com/JorgeCastilloPrz/ArrowAndroidSamples
Note how we build the complete program using fx and returning Kind at all levels in our architecture. That makes the code polymorphic to the type F, so you can run it using different runtime data types for F at will, depending on the environment. In this case we end up running it using IO at the edges. That's the activity in this case, but could also be the application class or a fragment. Think about this as what'd be the entry points to your apps. If we were talking about jvm programs the equivalent would be main(). This is just an example of how to write polymorphic programs, but you could use IO.fx instead and return IO everywhere, if you want to stay simpler.
Note how we use continueOn() in the data source inside the fx block to leave and come back to the main thread. Coroutine context changes are explicit in ArrowFx, so the computation jumps to the passed thread right after the continueOn until you deliberately switch again to a different one. That intentionally makes thread changes explicit.
You could inject those dispatchers to use different ones in tests. Hopefully I can provide examples of this soon in the repo, but you can probably imagine how this would look.
For the syntax on how to write tests note that your program will return Kind (if you go polymorphic) or IO, so you would unsafeRunSync it from tests (vs unsafeRunAsync or unsafeRunAsyncCancellable in production code since Android needs it to be asynchronous). That is because we want our test to be synchronous and also blocking (for the latter we need to inject the proper dispatchers).
Current caveats: The solution proposed in the repo still doesn't care of cancellation, lifecycle or surviving config changes. That's something I'd like to address soon. Using ViewModels with a hybrid style might have a chance. This is Android so I'd not fear hybrid styles if that brings better productivity. Another alternative I've got in mind would maybe be something a bit more functional. ViewModels end up retaining themselves using the retain config state existing APIs under the hood by using the ViewModelStore. That ultimately sounds like a simple cache that is definitely a side effect and could be implemented wrapped into IO. I want to give a thought to this.
I would definitely also recommend reading the complete ArrowFx docs for better understanding: https://arrow-kt.io/docs/fx/ I think it would be helpful.
For more thoughts on approaches using Functional Programming and Arrow to Android you can take a look to my blog https://jorgecastillo.dev/ my plan is to write deep content around this starting 2020, since there's a lot of people interested.
In the other hand, you can find me or any other Arrow team maintainers in the Kotlinlang JetBrains Slack, where we could have more detailed conversations or try to resolve any doubts you can have https://kotlinlang.slack.com/
As a final clarification: Functional Programming is just a paradigm that resolves generic concerns like asynchrony, threading, concurrency, dependency injection, error handling, etc. Those problems can be found on any program, regardless of the platform. Even within an Android app. That is why FP is an option as valid for mobile as any other one, but we are still into explorations to provide the best APIs to fulfill the usual Android needs in a more ergonomic way. We are in the process of exploration in this sense, and 2020 is going to be a very promising year.
Hopefully this helped! Your thoughts seem to be well aligned with how things should work in this approach overall.

Related

Map multiple suspend functions to single LiveData

The company I just started working at uses a so called Navigator, which I for now interpreted as a stateless ViewModel. My Navigator receives some usecases, with each contains 1 suspend function. The result of any of those usecases could end up in a single LiveData. The Navigator has no coroutine scope, so I pass the responsibility of scoping suspending to the Fragment using fetchValue().
Most current code in project has LiveData in the data layer, which I tried not to. Because of that, their livedata is linked from view to dao.
My simplified classes:
class MyFeatureNavigator(
getUrl1: getUrl1UseCase,
getUrl1: getUrl1UseCase
) {
val url = MediatorLiveData<String>()
fun goToUrl1() {
url.fetchValue { getUrl1() }
}
fun goToUrl2() {
url.fetchValue { getUrl2() }
}
fun <T> MediatorLiveData<T>.fetchValue(provideValue: suspend () -> T) {
val liveData = liveData { emit(provideValue()) }
addSource(liveData) {
removeSource(liveData)
value = it
}
}
}
class MyFeatureFragment : Fragment {
val viewModel: MyFeatureViewModel by viewModel()
val navigator: MyFeatureNavigator by inject()
fun onViewCreated() {
button.setOnClickListener { navigator.goToUrl1() }
navigator.url.observe(viewLifecycleOwner, Observer { url ->
openUrl(url)
})
}
}
My two questions:
Is fetchValue() a good way to link a suspend function to LiveData? Could it leak? Any other concerns?
My main reason to only use coroutines (and flow) in the data layer, is 'because Google said so'. What's a better reason for this? And: what's the best trade off in being consistent with the project and current good coding practices?
Is fetchValue() a good way to link a suspend function to LiveData?
Could it leak? Any other concerns?
Generally it should work. You probably should remove the previous source of the MediatorLiveData before adding new one, otherwise if you get two calls to fetchValue in a row, the first url can be slower to fetch, so it will come later and win.
I don't see any other correctness concerns, but this code is pretty complicated, creates a couple of intermediate objects and generally difficult to read.
My main reason to only use coroutines (and flow) in the data layer,
is 'because Google said so'. What's a better reason for this?
Google has provided a lot of useful extensions to use coroutines in the UI layer, e.g. take a look at this page. So obviously they encourage people to use it.
Probably you mean the recommendation to use LiveData instead of the Flow in the UI layer. That's not a strict rule and it has one reason: LiveData is a value holder, it keeps its value and provides it immediately to new subscribers without doing any work. That's particularly useful in the UI/ViewModel layer - when a configuration change happens and activity/fragment is recreated, the newly created activity/fragment uses the same view model, subscribes to the same LiveData and receives the value at no cost.
At the same time Flow is 'cold' and if you expose a flow from your view model, each reconfiguration will trigger a new flow collection and the flow will be to execute from scratch.
So e.g. if you fetch data from db or network, LiveData will just provide the last value to new subscriber and Flow will execute the costly db/network operation again.
So as I said there is no strict rule, it depends on the particular use-case. Also I find it very useful to use Flow in view models - it provides a lot of operators and makes the code clean and concise. But than I convert it to a LiveData with help of extensions like asLiveData() and expose this LiveData to the UI. This way I get best from both words - LiveData catches value between reconfigurations and Flow makes the code of view models nice and clean.
Also you can use latest StateFlow and SharedFlow often they also can help to overcome the mentioned Flow issue in the UI layer.
Back to your code, I would implement it like this:
class MyFeatureNavigator(
getUrl1: getUrl1UseCase,
getUrl1: getUrl1UseCase
) {
private val currentUseCase = MutableStateFlow<UseCase?>(null)
val url = currentUseCase.filterNotNull().mapLatest { source -> source.getData()}.asLiveData()
fun goToUrl1() {
currentUseCase.value = getUrl1
}
fun goToUrl2() {
currentUseCase.value = getUrl2
}
}
This way there are no race conditions to care about and code is clean.
And: what's the best trade off in being consistent with the project
and current good coding practices?
That's an arguable question and it should be primarily team decision. In most projects I participated we adopted this rule: when fixing bugs, doing maintenance of existing code, one should follow the same style. When doing big refactoring/implementing new features one should use latest practices adopted by the team.

Correct way to use Service for network communcation

I have classes MainActivity and MyService. In service I connect with a server, but I also need to update some UI for which I would need Context from MainActivity. More precisely I need to use a layoutInflater and then update the views. Should this be done separately?
Example of one function
private suspend fun setStations(serverText: String) {
withContext(Main) {
for (i in (1..numStations(serverText)))
{
frame = ScrollView( ) //would need context here
layoutInflater.inflate(R.layout.frame_layout, frame)
.
.
.
Generally, you would want to separate your business logic and UI concerns as much as possible, to make the code more readable and testable. To do so, you can follow architectural patters such as MVP, MVVM or MVI, based on the need and complexity of your app.
Thus, in your case you can potentially have a callback setup in your activity, that is called when the service finishes executing its code.
For reference, here are a few great reads for this:
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
https://antonioleiva.com/clean-architecture-android/
Also, here's a sample project that uses MVVM (a pretty common architecture)
https://github.com/skydoves/Pokedex
Typically, such a relationship is organized by the architectural pattern (model view presenter). You should make requests to the server in the presenter and then refer to Activity. This might help you https://github.com/Arello-Mobile/Moxy

How to send multiple commands from a MVVM to the View using the SingleLiveEvent class

I have a ViewModel in my android app, that has some logic, and the view needs to be adjusted/perform different things depending on the result of that logic. At first I tried to do it exclusively with observers and reacting to the state of the data in the viewmodel, but it was too complicated.
Then I found the concept of commands using the SingleLiveEvent class, and I found it good because it reminds me the same pattern when using Xamarin and the microsoft's mvvvm. One of the (few) good things that working with xamarin has ;)
Well, the problem in my case is that when I have more than one command that needs to be send to the view, the view is receiving only one command. Sometimes the last one, sometimes the first one. For example, a couple of commands that order the view to perform complicated things:
sealed class CustomCommands{
class CustomCommand1 : CustomCommands()
class CustomCommand2() : CustomCommands()
class CustomCommand3() : CustomCommands()
class CustomCommand4() : CustomCommands()
class CustomCommand5() : CustomCommands()
}
Then in my viewModel, I have the commands SingleLiveEvent object:
class CustomViewModel...{
val commands: SingleLiveEvent<CustomCommands> = SingleLiveEvent()
private fun doComplicatedThingsOnTheUI() {
GlobalScope.launch(Dispatchers.IO) {
if (someConditionsInvolvingRestRequestsAndDatabaseOperations()){
commands.postValue(CustomCommands.CustomCommand1())
commands.postValue(CustomCommands.CustomCommand2())
} else {
commands.postValue(CustomCommands.CustomCommand3())
commands.postValue(CustomCommands.CustomCommand4())
}
commands.postValue(CustomCommands.CustomCommand5())
}
}
}
And in the Activity/Fragment, I have the observer for the commands, that should react for each command and does the work:
class MainActivity...{
viewModel.commands.observe(this, Observer { command ->
Rlog.d("SingleLiveEvent", "Observer received event: " + command.javaClass.simpleName)
when (command) {
Command1->doSomething1()
Command2->doSomething2()
}
}
Well, the problem is that the view is normally receiving only the last command (Command5). But the behaviour depends on the api level of the Android SDK. By api 16, the view receives the last command. By Api 28, the view receives normally the first and the last command (for example, Command1 and Command5, but not Command2).
Maybe I'm understanding the capabilities of the SingleLiveEvent class wrong, or the whole Command thing wrong, but I need a way to allow the viewmodel to order the view to do somethings depending on the state of many objects and variables. The code above is only a sample, the reality es more complicated than that.
I don't want to use callbacks between the viewmodel and the view, because I read somewhere that that breaks the whole MVVM pattern.
Maybe someone has an advice for me. Any help would be welcome.
Thank you in advance.
I think I found a workaround, that seems to work (I have tested it only a couple of hours).
The thing is that I'm using "command.postValue(XXX)", because that piece of code is running inside a couroutine, that is, in other thread. Because of that I can not use command.value directly.
But the fact is that using command.value=Command1(), it works. I mean, the view receives all the commands sent, and very important too, with the same order as they were sent. Because of that I wrote a little funcion to send the commands to the UI switching the thread.
I'm not sure if this is correct, I'm a new to Kotlin coroutines and I have to admit that I don't understand them very well yet:
private suspend fun sendCommandToView(vararg icommands: CustomCommands) = withContext(Dispatchers.Main) {
icommands.forEach {
commands.value = it
}
}
And then I send the commands
sendCommandToView(CustomCommand1(),CustomCommand2(),CustomCommand5())
This seems to work. Thougt that the "post" method would work in a similar way, but it does not.
Regards.

LibGDX architecture design guidelines

I deal with loads of architecture design patterns and guidelines to choose from and to follow as an android client-server app developer.
The most popular ones are:
MVP or MVVM
Clean architecture
Repository pattern
Dependency injection technique
and so on...
Due to the strict rules of patterns, a developer has to admit the fact that patterns are just recommendations themselves, and are not required by Android SDK at all.
Same is true for LibGDX. There are no strict rules or requirements provided by LibGDX library, so the developer is free to decide how to write the game.
So the question is:
Are there some recommendations, design guidelines or even standards for LibGDX game developers to follow? How should I write the code (with usage of LibGDX) in a way that other developer can easily understand?
From my experiences, there is no standard everyone is following. libGDX developers come from different backgrounds. Some are backend developers in their day life, some are just hobbyist devs and learn their first development skills.
I see a lot of libGDX open-sourced projects with typical static SomeManager.getInstance() calls, while I prefer to pass-through references (as a backend developer, you will know about the advantages - testability and so on).
Even the libGDX backend itself does not follow one single approach. There are some parts getting references to managers by reflection (which is not good, because you must exclude such classes from obfusciation) and some using static getInstances().
If you also HTML5, you also must respect some GWT-based restrictions, so you are sometimes forced to go a way you would never do when developing Spring Boot applications.
Now that 3 years passed I can answer this question myself.
I found that using ECS (Entity-Component-System) is the best approach for creating games.
With this approach you'll have 3 different purpose objects. As name suggests they are:
Entity - is just a general purpose object which only contains set of component objects, and usually an ID.
Component - is a bag of data. No logic just plain POJO. The data it contains will define the behaviour of Entity which contains the component.
System - is where you put your logic. Every system should process an entity if and only if it contains a very specific set of components.
Engine - is a representation of a scene where all entities live, and are processed by systems.
The easies way of implementing such approach is by using Ashley lib. It's a lightweight implementation of ECS. Although as my experience has shown this works best in a case of real gameplay. If you want to have very specific animations (even of game objects) then use scene2d.
Scene2d represents a more familiar (to vast majority of developers) approach. It's a graph of UI elements which are placed in a hierarchy. There are very useful Actions which can be used to implement your animations. It also works best for any UI that you want to display in your game.
So to sum it all up I have worked out that you should have a couple of classes per screen to have a distinct division of labour.
Screen - I see it as a branch of running code. It contains an Engine (if we need an ECS) and a Stage (if we need an UI). Handles all game events, user input and routing.
Engine - ecs container which knows how to manage its systems, entities and components.
Stage - UI container which knows what UI elements should be present, how they should look and behave.
Simple example in kotlin (NOTE in my real project I use koin DI to bind all together):
class MyGameScreen : Screen, MyGameEngine.Callback, MyGameStage.Callback {
val engine = MyGameEngine(callback = this)
val stage = MyGameStage(callback = this)
override fun create() {
engine.create()
stage.create()
}
override fun render(delta: Float) {
enigne.update(delta)
stage.act(delta)
stage.draw()
}
override fun dispose() {
enigne.dispose()
stage.dispose()
}
override fun buttonPress() {
//handle button press
}
override fun onGameEvent(event: MyGameEngine.Event) {
//handle some game event
}
}
class MyGameEngine(
private val callback: Callback
) : com.badlogic.ashley.core.PooledEngine() {
fun create() {
// create and add all your systems and entities
}
sealed class Event {
// ...
}
interface Callback {
fun onGameEvent(event: Event)
}
}
class MyGameStage(
private val callback: Callback
) : com.badlogic.gdx.scenes.scene2d.Stage() {
val button1 = TextButton(...).apply {
addClickListener { callback.buttonPress() }
}
val label1 = Label(...)
// and so on
fun create() {
val root = Table().apply {
// add all your actors to the root table
}
val rootContainer = Container(root).apply {
setFillParent(true)
fill()
top()
}
addActor(rootContainer)
}
fun startSomeAnimation() {
val action = Actions.sequence(
// your animation
)
addAction(action)
}
interface Callback {
fun buttonPress()
}
}

Clean Coroutines usage in Kotlin with Unit Test support

Since a while we're working with Kotlin and one of the things we're currently focussing on is using Coroutines to take care of operations we want to run async.
While the example usages are clear and that works, I'm having some issues integrating this in a clean manner within our architecture. When looking at a method's implementation for a domain-focussed class, the idea is that it's easy to read and there is as less "noise" as possible from async functionality. I know I can't have async, without actually using it. So writing something like this is what I'd like:
val data = someService.getData().await()
// work with data
But this is what I'd like to prevent:
launch(UI) {
val data
val job = async(CommonPool) {
data = someService.getData()
}
job.await()
// work with data
}
That, I'd like paired with practical Unit Tests for these domain-focussed classes, but I can't really get that to work. Let's look at an example:
// Some dependency doing heavy work
class ApiClient {
suspend fun doExpensiveOperation(): String {
delay(1000)
return "Expensive Result Set"
}
}
// Presenter Class
class Presenter(private val apiClient: ApiClient,
private val view: TextView) {
private lateinit var data: String
fun start() {
log("Starting Presenter")
runBlocking {
log("Fetching necessary data")
data = apiClient.doExpensiveOperation()
log("Received necessary data")
}
workWithData()
log("Started Presenter")
}
fun workWithData() {
log(data)
}
private fun log(text: String) {
view.append(text+"\n")
}
}
// In an Activity
val presenter = Presenter(ApiClient(), someTextView)
presenter.start()
That works (screenshot: https://imgur.com/a/xG9Xw). Now lets look at the test.
class PresenterTest {
// ... Declared fields
#Before
fun setUp() {
// Init mocks (apiClient, textView)
MockitoAnnotations.initMocks(this)
// Set mock responses
runBlocking {
given(apiClient.doExpensiveOperation()).willReturn("Some Value")
}
presenter = Presenter(apiClient, textView)
}
#Test
#Throws(Exception::class)
fun testThat_whenPresenterStarts_expectedResultShows() {
// When
presenter.start()
// Then
Mockito.verify(textView).text = "Some Value\n"
}
}
Now this test is less than ideal, but regardless, it never even gets to the point where it can verify things work as intended, because lateinit var data wasn't initialized. Now ultimately the aesthetics and readability of our domain classes is simply how far I want to go, which I have some practical working examples for that I'm happy with. But making my tests work seems to be challenging.
Now there's some different write-ups online about this kind of stuff, but nothing has really worked out for me. This (https://medium.com/#tonyowen/android-kotlin-coroutines-unit-test-16e984ba35b4) seems interesting, but I don't like the idea of a calling class launching a context for a presenter, because that in turn has a dependency that does some async work. Although as an abstract thought I like the idea of "Hey presenter, whatever you do, report back to me on a UI context", it rather feels as a fix to make things work, leading to a shared concern for async functionality across different objects.
Anyway, my question:
Moving away from the short examples, does anyone have any pointers on how to integrate coroutines within a bigger architecture, with working unit tests? I'm also very open to arguments that make me alter my way of viewing things, given that's it's convincing on a different level than "If you want things to work, you have to sacrifice.". This question goes beyond just making the example work, as that is just an isolated example, while I'm looking for a real solid integration within a big project.
Looking forward to your input. Thanks in advance.
I'd suggest an approach of having some kind of AsyncRunner interface and have two implementations of this AsyncRunner interface. One would be implementation for Android, using launch(UI), and the other would be some blocking implementation, using runBlocking.
Passing the right type of AsyncRunner into code run within app and code run in unit test should be done by dependency injection. In your code then, you'd not use coroutines directly, instead you'd use injected AsyncRunner to run asynchronous code.
Example implementations of this AsyncRunner might look like this:
interface AsyncRunner {
fun <T>runAsync(task: () -> T, completion: (T) -> Unit)
}
class AndroidCoroutineAsyncRunner: AsyncRunner {
override fun <T>runAsync(task: () -> T, completion: (T) -> Unit) {
launch(UI) {
completion(async(CommonPool) { task() }.await())
}
}
}
class BlockingCoroutineAsyncRunner: AsyncRunner {
override fun <T>runAsync(task: () -> T, completion: (T) -> Unit) {
runBlocking {
completion(async(CommonPool) { task() }.await())
}
}
}
where the task parameter represents the thread blocking code (for example fetching data from API) and completion parameter will get data from the task and do something with them.
You should abandon coroutines and use RxJava instead. There you will find the kind of conciseness and simplicity you seek. When I ask most developers why they use coroutines, their answer is always the same: "Well, coroutines are the new, new thing, and we should use the latest technology from Google". Except that coroutines are not new. They were first introduced in about 1952 (See "Coroutines" in Wikipedia) as a proposal for doing asynchronous software development. It is pretty clear that the Computer Science community rejected coroutines years ago as not being the best approach for asynchronous programming. Why JetBrains decided to introduce an old, rejected technology into Kotlin is something you will have to ask JetBrains. I have had to deal with coroutines in code that others have written for several years now, and I always find coroutines to be needlessly complex. There is no way that coroutines do anything more than decrease maintainability when maintenance developers have to deal with coroutine spaghetti written by a developer who has long since departed the project.
The next thing I hear from these same developers is that RxJava is old technology and coroutines are new technology. If they had done their research, they would never have made such an outrageously incorrect statement. IMHO, RxJava is the most important new development in asynchronous software development in the entire history of computer science.

Categories

Resources