MutableStateFlow for methods - android-jetpack-compose

I’m trying to make my methods reactive to update the view in Compose. How to do it properly?
interface Foo{
val a: Int
fun bar(): Int
fun foo(): MutableStateFlow<Int> = MutableStateFlow(bar() * a)
}
//#Composable
val foo by fooImpl.foo().collectAsState()
P.S. Currently I made a hack: empty usage a variable a participated in calculations. But it’s not good.
val a = fooImpl.collectAsState()
a

One way to do it - subscribe to all variables used in a method.
var a = MutableStateFlow(0)
fun bar() = a.value +1
fun chad() = 42
fun foo() = bar() * chad()
val foo: Flow
get() = a.map { (it + 1) * chad() }
fun useFoo() = runBlocking {
withContext {
foo.collect {
something(it)
}
}
}

Related

Type mismatch: inferred type is data class but Int was expected

I'm fetching data from API. But I'm facing a problem, the LazyColumn items is not accepting the state vairable. I have this error:
Type mismatch: inferred type is Weather? but Int was expected
code:
#GET("/v1/forecast.json")
suspend fun getWeatherInfo(
#Query("key") apiKey:String = API_KEY,
#Query("q") country:String
):Weather
suspend fun getWeatherInfo(country:String):Weather{
return weatherApi.getWeatherInfo(country = country)
}
private val _state = mutableStateOf(WeatherState())
val state: State<WeatherState>
get() = _state
data class Weather(
#SerialName("current")
val current: Current,
#SerialName("forecast")
val forecast: Forecast,
#SerialName("location")
val location: Location
)
LazyColumn{
items(state.weather){
}
Any help?
So you are using wrong method. You should consider not using LazyColumn, as you probably do not need it, but if you do, it would be something like this:
val mutableState = mutableStateOf(WeatherState())
#Composable
fun LazyListWeather() {
LazyColumn {
item {
Text(text = mutableState.value.toString())
}
}
}
But IMO you do not need. You have only one Weather item. Just use simple column, if you do not have list of WeatherState

Optimization flag to remove redundant record allocations in F# code?

Consider this code:
type Foo =
{
X : int
Y : string
Z : int
}
module M =
let f foo =
let foo =
{
foo with
X = 123
}
let foo =
{
foo with
Y = "abc"
}
let foo =
{
foo with
X = foo.X + 1
}
foo
let g foo =
{
foo with
X = 123 + 1
Y = "abc"
}
Note that f and g do the same.
Using SharpLab, this is equivalent to:
// ...
[CompilationMapping(SourceConstructFlags.Module)]
public static class M
{
public static Foo f(Foo foo)
{
Foo foo2 = new Foo(123, foo.Y#, foo.Z#);
Foo foo3 = new Foo(123, "abc", foo2.Z#);
return new Foo(124, "abc", foo3.Z#);
}
public static Foo g(Foo foo)
{
return new Foo(124, "abc", foo.Z#);
}
}
// ...
Despite achieving the same thing, f allocates 3 times and g only once.
Is there a compiler flag or similar I can use to get f to compile more like g?
I'm almost certain what you're asking for doesn't exist and that every with involves a new copy. Adding the [<Struct>] attribute to your record might give you more performant allocation. See here for more details: https://bartoszsypytkowski.com/writing-high-performance-f-code/

Understanding Brackets in Dart (Flutter)

I have many confusion about Brackets in Dart(Flutter).
Which bracket "(), {}, []" is used for what?
() can group expressions:
var x = (1 + 2) * 3;
or can designate parameter lists for functions:
var getAnswer = () => 42;
int square(int x) => x * x;
or can designate function calls:
var answer = getAnswer();
var squared = square(4);
or is part of the syntax to some keywords. This includes (but is not limited to) if, assert, for, while, switch, catch:
if (condition) {
...
}
assert(condition);
for (var item in collection) {
...
}
while (condition) {
...
}
switch (value) {
...
}
try {
...
} on Exception catch (e) {
...
}
[] by itself creates List literals:
var list = [1, 2, 3];
var emptyList = []; // Creates a List<dynamic>.
or when used on an object, calls operator [], which usually accesses an element of a collection:
var element = list[index];
var value = map[key];
or in a parameter list, specifies optional positional parameters:
int function(int x, [int y, int z]) {
return x + y ?? 0 + z ?? 0;
}
function(1, 2);
or in dartdoc comments, creates linked references to other symbols:
/// Creates a [Bar] from a [Foo].
Bar fooToBar(Foo foo) {
// ...
}
{} can create a block of code, grouping lines together and limiting variable scope. This includes (but is not limited to) function bodies, class declarations, if-else blocks, try-catch blocks, for blocks, while blocks, switch blocks, etc.:
class Class {
int member;
}
void doNothing() {}
void function(bool condition) {
{
int x = 'Hello world!';
print(x);
}
if (condition) {
int x = 42; // No name collision due to separate scopes.
print(x);
}
}
or by itself can create Set or Map literals:
var set = {1, 2, 3};
var emptySet = <int>{};
var map = {'one': 1, 'two': 2, 'three': 3};
var emptyMap = {}; // Creates a Map<dynamic, dynamic>
or in a parameter list, specifies optional named parameters:
int function(int x, {int y, int z}) {
return x + y ?? 0 + z ?? 0;
}
function(1, y: 2);
or creates enumerations:
enum SomeEnumeration {
foo,
bar,
baz,
}
or in Strings is used to disambiguate interpolated expressions:
var foo = 'foo';
var foobar = '${foo}bar';
var s = '${function(1, 2)}';
<> when used as a pair in function or class declarations creates generics:
class GenericClass<T> {
T member;
}
T function<T>(T x) {
// ...
}
or specifies explicit types when using generics:
var map = <String, int>{};

Is it good practice to use run function instead of return in Kotlin?

Kotlin has an extension function run.
/**
* Calls the specified function [block] and returns its result.
*/
#kotlin.internal.InlineOnly
public inline fun <R> run(block: () -> R): R = block()
And run function can be used instead of return.
// an example multi-line method using return
fun plus(a: Int, b: Int): Int {
val sum = a + b
return sum
}
// uses run instead of return
fun plus(a: Int, b: Int): Int = run {
val sum = a + b
sum
}
Which style is better?
For more complicated functions the first option will be more readable.
For simple functions I would suggest taking a look at Single-expression function syntax.
fun plus(a: Int, b: Int): Int = a + b

Make WebSharper generate simple field access

I need a type that will be translated into a plain JS object so that F# field access will be translated into simple JS field access (this is necessary, since the object will be sent through postMessage, so it'll lose all its methods).
Again, I need
let x = a.b
to be translated into
var x = a.b;
without any method calls.
Here is a slightly modified example from the F# Reference:
namespace T
open IntelliFactory.WebSharper
[<JavaScript>]
module A =
type MyClass =
val a : int
val b : int
new(a0, b0) = { a = a0; b = b0; }
let myClassObj = new MyClass(35, 22)
let x = myClassObj.b
This won't translate with
x: error : Failed to translate property access: b.'
Ok, let's make those vals mutable:
namespace T
open IntelliFactory.WebSharper
[<JavaScript>]
module A =
type MyClass =
val mutable a : int
val mutable b : int
new(a0, b0) = { a = a0; b = b0; }
let myClassObj = new MyClass(35, 22)
let x = myClassObj.b
This will be successfully translated, but… MyClass.New returns an empty object. The question now starts looking much like a bugreport, right? So, back to the question.
Are there any other ways to achieve what I want?
There are additional issues with record-style constructors "{x = y}". I will have to look into this again on F# 3.0, the older F# did not produce sensible quotations for those and we did some partial workarounds in WebSharper. Right now your example breaks. So here is the working code with a static method instead of a constructor:
type MyClass private () =
[<DefaultValue>]
val mutable a : int
[<DefaultValue>]
val mutable b : int
static member Create(a0, b0) =
let c = MyClass()
c.a <- a0
c.b <- b0
c
let test () =
let myClassObj = MyClass.Create(35, 22)
let x = myClassObj.a
let y = myClassObj.b
JavaScript.Log(x, y)
Trivially, a record would also work.
In some cases where you want to go really low-level you can annotate members with the Inline attribute. When this is too much overhead you can use untyped API:
let x = obj ()
x?a <- 1
let y = x?a
JavaScript.Log(x, y)
try this:
type MyClass (a, b) =
member val A = a with get
member val B = b with get
let myClassObj = new MyClass(35, 22)
let x = myClassObj.B

Resources