Best way to get value from future in constructor in dart - flutter

what ways you suggest for getting value from future in object constructor ?
class F{
late SomeObj<t> _obj;
F(){
() async{
_obj = await someFuture();
}.call();
}
somefunc() => doing something with _obj
}
but this doesn't gave me right res in the right time,
Other ways for this situation?

Here are two possible approaches:
Make your class's constructor private and force callers to instantiate your class via an asynchronous static method. From the perspective of callers, there is little difference between calling a static method and a named constructor.
class F {
late SomeObj<T> _obj;
F._();
static Future<F> create() async {
var f = F._();
f._obj = await someFuture();
return f;
}
Object? someFunc() => doSomethingWith(_obj);
}
Explicitly make everything that depends on the asynchronous value also asynchronous. If _obj is initialized asynchronously, then _obj should be a Future. If someFunc depends on _obj, then someFunc should return a Future.
class F {
Future<SomeObj<T>> _obj;
F() : _obj = someFuture();
Future<Object?> someFunc() async => doSomethingWith(await _obj);
}

Related

Dart/Flutter: Use a 'final' variable, that is loaded asynchronously

I am running into an issue regading using a final variable that is still loaded in asynchronously still after initializing, hence throwing a 'Re-initializing Exception'. The problem is that I am initializing a final instance of class A inside of class B. But the classA's contructor seems to be doing some async work as well. As a result (seems to be the case after debugging), that the required arguments of classA are the only ones initialized when the instance is created. And when the rest of attributes of classA are initialized async, it tries remodifying the instance, throwing an Exception. The skeleton looks like:
class classA {
_mainAttribute;
_otherAttributes . . .;
//getters . . .
classA (this.mainAttribute) {
// async call
_waitForJsonParse().then((_jsonRoot) {
// initialize _otherAttributes;
}
}
Future _waitForJsonParse() async {
return await . . .;
}
}
class classB {
late final List<classA> _errorCausingAttr;
classB () {
// another async call
_loadAssetManifest().then((manifestMap) {
_errorCausingAttr = List.unmodifiable(
mainfestMap.getFolders()
.map((String folderName) => classA(folderName.someValue())
);
// Exception occurs here: "LateInitializationError:
//Field '_errorCausingAttr#33137322' has already been initialized.".
}
}
Future _loadAssetManifest() async {
return await . . .;
}
}
My first solution was to not use 'final' variables then. But is there a way to do it without sacrficing the kind of declaritive schemes? Maybe there is a better pattern / there is a code smell here?

Override/mock library functions for dart/flutter testing

I was wondering if there is a way to override library functions so they don't fire or just return something else.
import 'package:foo_package/exposing_foo_function.dart';
class TestableClass {
bool bar() {
return foo(); //foo is from the imported library
}
}
Test:
void main() {
test('TestableClass.bar() when foo_package.foo() returns false', () {
TestableClass testableClass = TestableClass();
// Something to make foo_package.foo() return false.
expect(testableClass.bar(), isFalse);
});
}
Things like mockito work by creating mock classes that implement the interface of the mocked class. That doesn't work for global and static functions, however.
What you instead can do is to avoid calling those global/static functions directly and instead call them through an extra level of indirection. For example:
import 'package:foo_package/exposing_foo_function.dart' as foo_package;
class TestableClass {
final bool Function() foo;
TestableClass({this.foo = foo_package.foo});
bool bar() {
return foo();
}
}
and then to test:
void main() {
test('TestableClass.bar() when foo_package.foo() returns false', () {
bool fakeFoo() => false;
TestableClass testableClass = TestableClass(foo: fakeFoo);
expect(testableClass.bar(), isFalse);
});
}
A similar approach is to wrap the global/static functions as instance methods of a class:
import 'package:foo_package/exposing_foo_function.dart' as foo_package;
class FooManager {
bool foo() => foo_package.foo();
}
var fooManager = FooManager();
class TestableClass {
bool bar() {
return fooManager.foo();
}
}
and then your tests can mock FooManager like any other class and set fooManager to the mocked version. (Or if you prefer dependency inversion to global variables, passing your mocked version of FooManager to TestableClass as a construction argument.)
Of course, all of the above will help only for your own calls that go through your wrappers. It won't help if code you don't control calls those functions. In that case, your best course of action might be to complain to the function's author about lack of testability.

ReactiveX and Dart

I have a class Too
class Too{
bool isLogged = false;
BehaviorSubject suject = BehaviorSubject<bool>();
Too({required this.isLogged}){
suject = new BehaviorSubject<bool>.seeded(isLogged);
}
void login(){
isLogged = true;
suject.sink.add(isLogged);
}
void logOut(){
isLogged = false;
suject.sink.add(isLogged);
}
void dispose(){
suject.close();
}
and I also have the Foo class:
class Foo{
Too _too = new Too(isLogged: false);
_too.stream.listen((event) { print('${event}');});
}
My issue is When the user is calling the login() method of the Too class nothing happens at the level of the Foo class.
What I want to do is that if the user calls the login() method of the Too class and his isLogged attribute is set to true, then this change is done at the level of all the classes that have an attribute of the Too type.
Note: It's much easier to do it with Angular or Ionic using RxJS, but with dart, I don't know how to implement this mechanism.
Foo is not reacting because its listening to a different instance of Too.
The way you have it is that each new instance of Foo creates a new instance of Too. If I understand you correctly, you want all instances of Foo to react to any change to a single instance of Too.
You can use a singleton for this.
class Too {
// one of a few ways to make a singleton in Dart
Too._();
static final _instance = Too._();
factory Too() {
return _instance;
}
final subject = BehaviorSubject<bool>.seeded(isLogged);
static bool isLogged = false;
void login() {
isLogged = true;
subject.sink.add(isLogged);
}
void logOut() {
isLogged = false;
subject.sink.add(isLogged);
}
void dispose() {
subject.close();
}
}
Now you can have any Foo object listen to the same Too instance.
class Foo {
Foo() {
Too().subject.stream.listen((event) {
print('foo $event'); // this will now print whenever a subject from your Too class is updated.
});
}
}
Now for example you could test this by creating a button with this as the onPressed.
onPressed: () {
final foo = Foo(); // just created an example of a Foo object that will
// print the updated value of the Too singleton
Too().login();
},
RxDart is great. However when it comes to reactive programming in Flutter, I suggest checking out Get X as it simplifies a lot of stream based stuff.

async/await problem when extend super class

I need to set the order of execution of my methods on the constructor of my supper class because i have a multiple class that extends from this supper class and the order is the same on all of them (take advantage of abstract class), but i am facing a strange problem where i get a result of a variable before the finishing of the future, this is a simulation code of my above description, you can try it on dartpad.dev:
abstract class SuperClass {
bool _success;
bool get isSuccess => _success;
set setSuccess(bool success) => this._success = success;
SuperClass() {
//checkLogin();
runCode();
//sendRequest();
}
runCode() async {
await doSomething();
}
Future<void> doSomething();
}
class SubClass extends SuperClass {
String text;
#override
Future<void> doSomething() async {
text = await Future.delayed(Duration(seconds: 2), () => '2 sec of getting data');
if (text.isNotEmpty) {
setSuccess = true;
print(text);
}
print('value of success is "$isSuccess" from the overriding method');
}
}
void main() async {
SubClass subClass = new SubClass();
// if (subClass.isSuccess) // how can i get success from the sub class
// do somthing else
print('value of success is "${subClass.isSuccess}"');
}
the result is :
value of success is "null"
2 sec of getting data
value of success is "true" from the overriding method
My question is why i get the value of the variable from the super class while i am running the future method before it and read it from the sub class ?
Did i miss something or how i can handle this logic ?
you need another method in the abstract class, when creating an object from the subclass, calling abstract class constructor automatically, you are calling "doSomething" override method in the constructor by "runCode" method, but since "doSomething" method is override method It will be called automatically in subclasses, So you need another method
If your question is about why you get the print in this order rather than:
2 sec of getting data
value of success is "true" from the overriding method
value of success is "true"
that is just because you call the async function runCode() in the constructor of SuperClass which is implicitly called when you create a SubClass as the latter inherits from the former. Since the method is async and you are not awaitint it, the method starts running on a different thread and code execution is not stoped there waiting for the runCode() method to return.
This means that runCode() starts executing in a different thread and immediately after that, the SuperClass constructor returns, the SubClass method (which implicitly called the former) also returns, and then your print statement from main executes. Since these steps take less than two seconds to execute, they finish executing before the rest of runCode()
Instead, you can remove the runCode() from the abstract class constructor and call the doSomething() method after initializing:
void main() async {
SubClass subClass = new SubClass();
await subClass.doSomething();
print('value of success is "${subClass.isSuccess}"');
}

Dart can you overload the assignment operator?

I have the following class:
class EventableNumber{
num _val;
num get val => _val;
void set val(num v){
num oldValue = _val;
_val = v;
_controller.add(new NumberChangedEvent(oldValue, v));
}
StreamController<NumberChangedEvent> _controller = new StreamController<NumberChangedEvent>();
Stream<NumberChangedEvent> _stream;
Stream<NumberChangedEvent> get onChange => (_stream != null) ? _stream : _stream = _controller.stream.asBroadcastStream();
EventableNumber([num this._val = 0]);
}
Is it possible to overload the = assignment operator? rather than using the val getter and setter to enforce the event to fire when the value changes it would be nice if it could just be done when the user writes myEventableNum = 34 and then myEventableNum first its onChange event, rather than myEventableNum.val = 34.
Dart doesn't allow this.
However, have you considered a function style call?
Basically, if you define a function called 'call' in EventableNumber class, then you can call the instance as a function:
myEventableNum(34)
If you decided to go this way, it is recommended to implement the Function interface:
class EventableNumber implements Function {
...
void call(val) {...}
...
}
Hope this helps :)