One thing I don't get it:
An app with master and detail views.
I want to supply a DAO class for each view.
Should I use a Multiprovider right after main() or should I use individual Providers in the views class?
I want to instatiate the classes only when the view is loaded. My question is do they get instantiated already if I put it on the top of the app or do they have like lazy instantiation
_Originally posted by @peekpt in https://github.com/rrousselGit/provider/issues/77#issuecomment-494551544_
Providers are not lazy-loaded, so the topic of "should I put a provider above MyApp or inside the view" is a valid question.
The general answer is "it depends".
We need some examples showing how to lazy-load information using provider.
After some dig-in in Flutter sources, and once a PR land, provider may be able to do more than expected.
I made a POC of a lazy loading InheritedWidget here https://github.com/rrousselGit/lazy_provider
After some more playing around, I made an initial implementation of lazy-loaded providers on the branch lazy: https://github.com/rrousselGit/provider/tree/lazy
This currently adds a constructor to Provider:
Provider.lazy(
builder: (context) => Foo(),
child: <whatever>
);
where builder is called the first time Provider.of<Foo> is called, instead of the first time Provider<Foo> is built.
That logic could be applied to all providers.
On the other hand, a maintainState-like variable can only be made after a PR on Flutter.
Just a reminder how to test branches
provider:
git:
url: https://github.com/rrousselGit/provider.git
ref: lazy
path: packages/provider
I can't get this to work.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() => runApp(Provider<Foo>.lazy(
builder: (_) {
Foo('bar');
print('Foo is provided');
},
child: MaterialApp(
title: 'Lazy Provider',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Home()),
));
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
print('Home Page build');
onPressed() {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => NextPage()));
}
return Scaffold(
appBar: AppBar(title: Text('Lazy Provider')),
body: Center(
child: RaisedButton(
onPressed: onPressed,
child: Text('Go to Next Page'),
)),
);
}
}
class NextPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
print('Next Page build');
return Scaffold(
body: Center(
child: Consumer<Foo>(
builder: (ctx, foo, widget) {
print('Consuming...');
return Text(foo?.name ?? 'error');
},
),
),
);
}
}
class Foo {
final String name;
Foo(this.name) {
print('Foo inited with $name');
}
}
Restarted application in 1 377ms.
I/flutter (16414): Home Page build
I/flutter (16414): Next Page build
I/flutter (16414): Foo inited with bar
I/flutter (16414): Foo is provided
I/flutter (16414): Consuming...
What do you mean by that? From the logs it looks like it worked
It shows 'error' . The foo is null
A sábado, 15/06/2019, 19:14, Remi Rousselet notifications@github.com
escreveu:
What do you mean by that? From the logs it looks like it worked
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/rrousselGit/provider/issues/81?email_source=notifications&email_token=AABWJMLGLWI6LC2IQ6FQQELP2UWPVA5CNFSM4HOOTDD2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODXY5LQI#issuecomment-502388161,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AABWJMOEJWXFASZ7D226FODP2UWPVANCNFSM4HOOTDDQ
.
That's because your provider's builder doesn't return anything.
yes, that's it! It worked. Thank you! it's weird how dart analyzer doesn't complain about it.
One question please: when Provider is lazy loaded the widget level of the Provider remains on top, or starts where it was instantiated?
In your example, the widget is still technically on the top of everything.
The only difference is that builder is not called immediately.
@rrousselGit Any word on when this new feature will be ready, since this will make it easier for me to inject lazily created scoped dependencies to a given widget. Thanks in advance.
It should be available within a 2 weeks span.
I waited for https://github.com/flutter/flutter/pull/33213 for a second feature that works in combination with lazy-loading.
But the Flutter team isn't convinced, so I'll start lazy-loading as a standalone feature.
@rrousselGit Sorry for pestering you again, just wondering the current status of this feature. I noticed that it's currently Pull Requested, but no movement has been made on it for over a month. Thanks in advance.
Ah right, sorry for that. I got absorbed by other things.
The basics are fine, and I can make a preview release. But there are still some things I'm not too sure about.
After all, it's technically a breaking change (almost it's not for most use cases), which implies a 4.0.0.
But i have a few other things in mind for a 4.0.0.
Is a 4.0.0-dev alright for now?
I can also make an issue with all the things I have in mind for such version, if you want to comment on it.
A 4.0.0-dev preview might suffice for the time being. It's your call though.
Alternatively, if the basics are fine, this could warrant an MVP minor release. Then again, the breaking change factor definitely makes it a major change.
It's a tough call but it's yours to make ultimately. What's the scope of the breaking changes to be exact? That would help us determine whether a minor release for a basic lazy implementation is warranted. Then you can follow that up with more lazy functionality in the next major release at your own pace.
XXProvider(builder: (_) => Whatever()) would go from non-lazy-loaded to lazy-loaded.
That's a breaking change, because someone may want to voluntarily pre-load the object (to make an http-requests earlier for example).
@rrousselGit Is there a possibility that you can make lazy provider functionality either as an optional parameter (i.e. lazyBuilder) which if present, uses that builder instead of the default one, or as a factory method that instantiates it in a different way, hiding the use of this lazy builder?
That way, you can mitigate any potential API breakage by making it opt-in instead of permanent, which is what you're proposing. In a future major release, you can most certainly make this current behavior permanent. However, for now, it might make sense to isolate it from the main constructor to provide for a smooth transition.
I don't like the idea of making a stable release, knowing that the API is not ideal and will need a breaking change.
And there are still things that need to be decided, such as: how to lazy load an object, but scope it to a Route?
Because currently, scoping to a route relies on the .value variant of providers, which means no lazy-loading.
Alright sorry for the delay.
I'm working full time on it now and got a good chunk of it down in https://github.com/rrousselGit/provider/pull/240
Everything but Stream/FutureProvider/ValueListenableProvider are migrated, including the *Proxy variant.
The next step is a lot of tests, and merging *Provider and *ProxyProvider (deprecating *Proxy).
Most helpful comment
It should be available within a 2 weeks span.
I waited for https://github.com/flutter/flutter/pull/33213 for a second feature that works in combination with lazy-loading.
But the Flutter team isn't convinced, so I'll start lazy-loading as a standalone feature.