Flutter: Run method on Widget build complete - dart

I would like to be able to run functions once a Widget has finished building/loading but I am unsure how.
My current use case is to check if a user is authenticated and if not, redirect to a login view. I do not want to check before and push either the login view or the main view, it needs to happen after the main view has loaded.
Is there anything I can use to do this?

You could use
https://github.com/slightfoot/flutter_after_layout
which executes a function only one time after the layout is completed.
Or just look at its implementation and add it to your code :-)
Which is basically
void initState() {
super.initState();
WidgetsBinding.instance
.addPostFrameCallback((_) => yourFunction(context));
}

UPDATE: Flutter v1.8.4
Both mentioned codes are working now:
Working:
WidgetsBinding.instance
.addPostFrameCallback((_) => yourFunction(context));
Working
import 'package:flutter/scheduler.dart';
SchedulerBinding.instance.addPostFrameCallback((_) => yourFunction(context));

Best ways of doing this,
1. WidgetsBinding
WidgetsBinding.instance.addPostFrameCallback((_) {
print("WidgetsBinding");
});
2. SchedulerBinding
SchedulerBinding.instance.addPostFrameCallback((_) {
print("SchedulerBinding");
});
It can be called inside initState, both will be called only once after Build widgets done with rendering.
#override
void initState() {
// TODO: implement initState
super.initState();
print("initState");
WidgetsBinding.instance.addPostFrameCallback((_) {
print("WidgetsBinding");
});
SchedulerBinding.instance.addPostFrameCallback((_) {
print("SchedulerBinding");
});
}
both above codes will work the same as both use the similar binding framework.
For the difference find the below link.
https://medium.com/flutterworld/flutter-schedulerbinding-vs-widgetsbinding-149c71cb607f

There are 3 possible ways:
1) WidgetsBinding.instance.addPostFrameCallback((_) => yourFunc(context));
2) Future.delayed(Duration.zero, () => yourFunc(context));
3) Timer.run(() => yourFunc(context));
As for context, I needed it for use in Scaffold.of(context) after all my widgets were rendered.
But in my humble opinion, the best way to do it is this:
void main() async {
WidgetsFlutterBinding.ensureInitialized(); //all widgets are rendered here
await yourFunc();
runApp( MyApp() );
}

Flutter 1.2 - dart 2.2
According with the official guidelines and sources if you want to be certain that also the last frame of your layout was drawned you can write for example:
import 'package:flutter/scheduler.dart';
void initState() {
super.initState();
if (SchedulerBinding.instance.schedulerPhase == SchedulerPhase.persistentCallbacks) {
SchedulerBinding.instance.addPostFrameCallback((_) => yourFunction(context));
}
}

If you are looking for ReactNative's componentDidMount equivalent, Flutter has it. It's not that simple but it's working just the same way. In Flutter, Widgets do not handle their events directly. Instead they use their State object to do that.
class MyWidget extends StatefulWidget{
#override
State<StatefulWidget> createState() => MyState(this);
Widget build(BuildContext context){...} //build layout here
void onLoad(BuildContext context){...} //callback when layout build done
}
class MyState extends State<MyWidget>{
MyWidget widget;
MyState(this.widget);
#override
Widget build(BuildContext context) => widget.build(context);
#override
void initState() => widget.onLoad(context);
}
State.initState immediately will be called once upon screen has finishes rendering the layout. And will never again be called even on hot reload if you're in debug mode, until explicitly reaches time to do so.

In flutter version 1.14.6, Dart version 28.
Below is what worked for me, You simply just need to bundle everything you want to happen after the build method into a separate method or function.
#override
void initState() {
super.initState();
print('hello girl');
WidgetsBinding.instance
.addPostFrameCallback((_) => afterLayoutWidgetBuild());
}

The PostFrameCallback fires before the screen has fully painted. Therefore Devv's answer above was helpful with the added delay to allow the screen to paint.
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
Future.delayed(Duration(seconds: 3), () => yourFunction());
});
}

Try SchedulerBinding,
SchedulerBinding.instance
.addPostFrameCallback((_) => setState(() {
isDataFetched = true;
}));

if you having issue with new SDK and old answer you can try my solution.I have tested it on v3.0.4
WidgetsBinding.instance.endOfFrame.then(
(_) {
if (mounted) {
// do some suff
// you can get width height of specific widget based on GlobalKey
};
},
);

If you don't want to use WidgetsBinding or SchedulerBinding:
Use Future or Timer (easy-peasy)
Future<void> _runsAfterBuild() async {
// This code runs after build ...
}
#override
Widget build(BuildContext context) {
Future(_runsAfterBuild); // <-- Use Future or Timer
return Container();
}
Await a dummy Future
Future<void> _runsAfterBuild() async {
await Future((){}); // <-- Dummy await
// This code runs after build ...
}
#override
Widget build(BuildContext context) {
_runsAfterBuild();
return Container();
}

my english is poor
forgive me
import 'package:flutter/material.dart';
class TestBox extends StatefulWidget {
final Color color;
final Duration delay;
const TestBox({
Key? key,
this.color = Colors.red,
this.delay = const Duration(seconds: 5),
}) : super(key: key);
#override
_TestBoxState createState() => _TestBoxState();
}
class _TestBoxState extends State<TestBox> {
String? label;
#override
void initState() {
initialMembers();
super.initState();
}
void initialMembers() async {
label = await fetchLabel();
if (mounted) setState(() {});
/// don't worry
/// if `(!mounted)`, means wen `build` calld
/// the label already has the newest value
}
Future<String> fetchLabel() async {
await Future.delayed(widget.delay);
print('fetchLabel call');
return 'from fetchLabel()';
}
#override
Widget build(BuildContext context) {
return AnimatedContainer(
margin: EdgeInsets.symmetric(vertical: 12),
duration: Duration(milliseconds: 500),
width: 220,
height: 120,
color: label == null ? Colors.white : widget.color,
child: Center(
child: Text(label ?? 'fetching...'),
),
);
}
}
Column(
children: [
TestBox(
delay: Duration(seconds: 1),
color: Colors.green,
),
TestBox(
delay: Duration(seconds: 3),
color: Colors.yellow,
),
TestBox(
delay: Duration(seconds: 5),
color: Colors.red,
),
],
),

I have a Stateful widget where I use html_editor_enhanced plugin widget. This is the only way to set initial message in it.
class _SendChatMessageState extends State<SendChatMessage> {
final _htmlController = HtmlEditorController();
#override
void initState() {
super.initState();
Future.delayed(const Duration(seconds: 3), () {
_htmlController.setText(widget.chatMessage.message ?? '');
});
}
I tried addPostFrameCallback but it didn't work because a JavaScript generates exception "HTML editor is still loading, please wait before evaluating this JS ..."

another solution that worked pretty well for me is wrapping the function you want to call by Future.delayed() as showen below:
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
Future.delayed(Duration(seconds: 3), () => yourFunction());
});
}

Related

Equivalent of viewWillAppear() in Flutter

I'm rebuilding an iOS app using Flutter and the flow is as followed:
Everytime the user lands on the homepage, the user data is reloaded from the backend to check if anything has changed.
The way I achieve this in Swift / iOS is by using the viewDidLoad() function.
My Flutter code is like this:
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
User user = User();
#override
void dispose() {
super.dispose();
}
#override
void initState() {
super.initState();
_fetchData(context);
}
#override
Widget build(BuildContext context) {
return Container(
color: RColor.COLOR_main,
child: Column(
children: [
Container(
height: MediaQuery.of(context).size.height / 7,
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.all(20),
child: Container(
child: Text("This is the homepage"),
alignment: Alignment.bottomCenter,
),
),
],
));
}
Future _fetchData(BuildContext context) async {
_fetchUserAPI(context);
}
Future _fetchUserAPI(BuildContext context) async {
try {
SharedPreferences prefs = await SharedPreferences.getInstance();
var accessToken = prefs.getString("access_token");
var url = RConstants.API_BASE_URL + "/v1/users/self";
Response response = await Dio()
.get(url, options: Options(headers: {"Authorization": accessToken}));
setState(() {
user = User.fromJson(response.data);
});
} catch (e) {
print(e.toString());
Alert(
context: context,
title: "Something Went Wrong",
desc: "Something went wrong while fetching your user data",
type: AlertType.error)
.show();
}
}
}
void initState() however, doesn't get triggered each time the user lands on the homepage. What is the correct way to achieve this?
Well, it really depends on what exactly you mean by "Everytime the user lands on the homepage".
If user navigates from the HomePage to some other view via Navigator.push and then goes back via Navigator.pop then the HomePage's state remain the same and of course the initState method does not trigger.
If you want to get notified on the HomePage if the route above it in the navigator gets popped then you need to use this method, override it and then inside it you will be able to call the _fetchData() and update the homepage's state.
One more thing: when you have some async call like _fetchData() it is a wrong pattern to just invoke it inside the initState() or any other framework methods. Because it will be invoked and the build() method of your state will almost always be invoked immediately before the result of async call will come back. The correct way to handle such situations is to use the FutureBuilder widget.
If "Everytime the user lands on the homepage" means something else, like e.g. the app was in the background and gets brought foreground or when there is support for push notifications implemented and users click on the notification and the app is opened - such cases also can be handled but that is a broader topic.
RouteAware can help.
define final RouteObserver<ModalRoute<void>> routeObserver = RouteObserver<ModalRoute<void>>(); in main.dart.
set navigatorObservers: [ routeObserver ], in MaterialApp function.
mixin RouteAware in your page that need achieve viewWillAppear feature.
override didChangeDependencies and didPopNext methods and subscribe this page to routeObserver.
For example:
main.dart
final RouteObserver<ModalRoute<void>> routeObserver = RouteObserver<ModalRoute<void>>();
void main() {
runApp(MaterialApp(
home: HomePage(),
navigatorObservers: [ routeObserver ],
));
}
home_page.dart
class _HomePageState extends State<HomePage> with RouteAware {
#override
void didChangeDependencies() {
super.didChangeDependencies();
routeObserver.subscribe(this, ModalRoute.of(context)!);
}
#override
void dispose() {
routeObserver.unsubscribe(this);
super.dispose();
}
#override
void didPopNext() {
super.didPopNext();
debugPrint("viewWillAppear");
}
}

How to fix FutureBuilder open multiple times error?

these my two classes(two pages). these two classes open multiple times.
I put debug point in futurebuilder in two classes.
debug point running,
MainCategory page and got to the next page
SubCategory page and again running MainCategory page(previous page) futurebuilder and again running MainCategory page futurebuilder
navigate subcategory page to third page running subcategory page and main category page
I upload my two classes to GitHub and please let me know what the issue is.
MainCategory code: https://github.com/bhanuka96/ios_login/blob/master/MainCategory.dart
SubCategory code: https://github.com/bhanuka96/ios_login/blob/master/subCategory.dart
As stated in the documentation, you should not fetch the Future for the Futurebuilder during the widget's build event.
https://docs.flutter.io/flutter/widgets/FutureBuilder-class.html
The future must have been obtained earlier, e.g. during
State.initState, State.didUpdateConfig, or
State.didChangeDependencies. It must not be created during the
State.build or StatelessWidget.build method call when constructing the
FutureBuilder. If the future is created at the same time as the
FutureBuilder, then every time the FutureBuilder's parent is rebuilt,
the asynchronous task will be restarted.
So, try to move your call to getRegister method outside the build method and replace it with the returned Future value.
For example, below I have a class that returns a Future value which will be consumed with the help of FutureBuilder.
class MyApiHelper{
static Future<List<String>> getMyList() async {
// your implementation to make server calls
return List<String>();
}
}
Now, inside your widget, you will have something like this:
class _MyHomePageState extends State<MyHomePage> {
Future<List<String>> _myList;
#override
void initState() {
super.initState();
_myList = MyApiHelper.getMyList();
}
#override
Widget build(BuildContext context) {
return Scaffold(body: FutureBuilder(
future: _myList,
builder: (_, AsyncSnapshot<List<String>> snapLs) {
if(!snapLs.hasData) return CircularProgressIndicator();
return ListView.builder(
itemCount: snapLs.data.length,
itemBuilder: (_, index) {
//show your list item row here...
},
);
},
));
}
}
As shown above, the Future is fetched in the initState function and used inside the build method and used by FutureBuilder.
I hope this was helpful.
Thanks.
If you happen to use Provider, here's (in my opinion) a clearer alternative based on your question:
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return FutureProvider<List<String>>(
create: (_) => MyApiHelper.getMyList(),
child: Consumer<List<String>>(
builder: (_, list, __) {
if (list == null) return CircularProgressIndicator();
return ListView.builder(
itemCount: list.length,
itemBuilder: (_, index) {
//show your list item row here...
},
);
};
),
);
}
}
This can also be achieved of course as a StatefulWidget as suggested by the other answer, or even with flutter_hooks as explained in Why is my Future/Async Called Multiple Times?
You can create new Widget and pass Function to
returnFuture as
() {
return YourFuture;
}
import 'dart:developer';
import 'package:flutter/material.dart';
class MyFutureBuilder<T> extends StatefulWidget {
final Future<T> Function() returnFuture;
final AsyncWidgetBuilder<T> builder;
final T initialData;
MyFutureBuilder({
this.returnFuture,
#required this.builder,
this.initialData,
Key key,
}) : super(key: key);
#override
_MyFutureBuilderState<T> createState() => _MyFutureBuilderState<T>();
}
class _MyFutureBuilderState<T> extends State<MyFutureBuilder<T>> {
bool isLoading = false;
Future<T> future;
#override
void initState() {
super.initState();
future = widget.returnFuture();
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
builder: widget.builder,
initialData: widget.initialData,
future: future,
);
}
}
Example
MyFutureBuilder<List<User>>(
returnFuture: () {
return moderatorUserProvider
.getExecutorsAsModeratorByIds(val.users,
save: true);
},
builder: (cont, asyncData) {
if (asyncData.connectionState !=
ConnectionState.done) {
return Center(
child: MyCircularProgressIndicator(
color: ModeratorColor.executors.color,
),
);
}
return Column(
children: asyncData.data
.map(
(singlExecutor) =>
ChooseInfoButton(
title:
'${singlExecutor.firstName} ${singlExecutor.secondName}',
subTitle: 'Business analyst',
middleText: '4.000 NOK',
subMiddleText: 'full time',
label: 'test period',
subLabel: '1.5 month',
imageUrl:
assetsUrl + 'download.jpeg',
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) =>
ModeratorExecutorEditPage(),
),
);
},
),
)
.toList());
},
)
```

FLUTTER: How to show dialog before beginning of the app?

I want to show a confirmation alert dialog right before opening the app, can someone please tell me how can I achieve that in flutter?
The showDialog() method needs a context, hence I should put it somewhere with buildContext, I assume in app's build method, but how can I trigger the dialog before the actual layout will be built on screen?
In your initState you can add your callback which will show your dialog with WidgetsBinding.instance.addPostFrameCallback which will be displayed immediately after layout. You can update your layout state according to your dialog result.
class HomePageState extends State<HomePage> {
#override
void initState() {
super.initState();
WidgetsBinding.instance
.addPostFrameCallback((_) => showDialog(...));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('HomePage'),
),
body: Container(),
);
}
Code below works, I guess this is the answer
#override
Widget build(BuildContext context) {
Future.delayed(Duration.zero, () => showAlert(context));
return new WhateverLayoutYouWantToBeDisplayed();
}
void showAlert(BuildContext context) {
showDialog(
child: new WhateverCustomDialogYouHave(),
context: context);
}
Best ways of doing this,
1. WidgetsBinding
WidgetsBinding.instance.addPostFrameCallback((_) {
showDialog();
});
2. SchedulerBinding
SchedulerBinding.instance.addPostFrameCallback((_) {
showDialog();
});
WidgetsBinding & SchedulerBinding will be called only once as we called it in initState(), but remember it will be called when the build method finished its rendering.
void initState() {
// TODO: implement initState
super.initState();
print("initState");
WidgetsBinding.instance.addPostFrameCallback((_) {
print("WidgetsBinding");
});
SchedulerBinding.instance.addPostFrameCallback((_) {
print("SchedulerBinding");
});
}
Detail Description: https://medium.com/flutterworld/flutter-schedulerbinding-vs-widgetsbinding-149c71cb607f

Test breaks when using Future.delayed

I have used a Future.delayed to show a FAB in 1 second using this code:
Future.delayed(const Duration(seconds: 1), () {
setState(() {
_showFab = true;
});
});
Now the most basic smoke test has stopped working:
void main() {
testWidgets('smoke test', (WidgetTester tester) async {
await tester.pumpWidget(MyApp());
expect(find.byType(MyHomePage), findsOneWidget);
});
}
This is the error message:
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following assertion was thrown running a test:
A Timer is still pending even after the widget tree was disposed.
'package:flutter_test/src/binding.dart': Failed assertion: line 933 pos 7:
'_currentFakeAsync.nonPeriodicTimerCount == 0' import 'dart:async';
Here is all the code used:
import 'package:flutter/material.dart';
import 'dart:async';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _showFab = false;
#override
Widget build(BuildContext context) {
Future.delayed(const Duration(seconds: 1), () {
setState(() {
_showFab = true;
});
});
return Scaffold(
floatingActionButton: AnimatedOpacity(
opacity: _showFab ? 1.0 : 0.0,
duration: Duration(milliseconds: 1400),
child: FloatingActionButton(
onPressed: null,
child: Icon(Icons.add),
),
),
);
}
}
How can I change the unit test to make the test pass?
The test framework runs with FakeAsync by default, that has some limitations and might cause the error you get.
You can explicitly run with async proper like:
void main() {
testWidgets('smoke test', (WidgetTester tester) async {
await tester.runAsync(() async {
await tester.pumpWidget(MyApp());
expect(find.byType(MyHomePage), findsOneWidget);
});
});
}
You might still need suggestions made in other answers.
You need to give the tester enough time to process all the async calls you have scheduled, try change your smoke test to something like this:
void main() {
testWidgets('smoke test', (WidgetTester tester) async {
await tester.pumpWidget(MyApp());
// Since you wait 1 second to start the animation and another 1.4 to complete it
await tester.pump(Duration(seconds: 3));
expect(find.byType(MyHomePage), findsOneWidget);
});
}
You will also need to move the Future.delayed out of the build() method, because this is causing a cyclic behaviour, every time you call setState() the build() is called again, change your state like that:
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _showFab = false;
#override
void initState() {
Future.delayed(const Duration(seconds: 1), () {
setState(() {
_showFab = true;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: AnimatedOpacity(
opacity: _showFab ? 1.0 : 0.0,
duration: Duration(milliseconds: 1400),
child: FloatingActionButton(
onPressed: null,
child: Icon(Icons.add),
),
),
);
}
}
You can wrap your Widget with TickerMode.
As you can see below:
void main() {
testWidgets('smoke test', (WidgetTester tester) async {
await tester.pumpWidget(TickerMode(child: MyApp(), enabled: false));
await tester.pumpAndSettle();
expect(find.byType(MyHomePage), findsOneWidget);
});
}
Try calling pumpAndSettle after you've pumped the widget. Like this:
void main() {
testWidgets('smoke test', (WidgetTester tester) async {
await tester.pumpWidget(MyApp());
await tester.pumpAndSettle();
expect(find.byType(MyHomePage), findsOneWidget);
});
}
From the docs
This essentially waits for all animations to have completed.
I tried using pump and pumpAndSettle but it didn't work. But add Duration in pumpAndSettle (not work for pump) makes it work again
await tester.pumpAndSettle(Duration(seconds: 1));

Flutter camera frame drops when switching between pages

I have tried to use the Flutter camera plugin (0.2.1) in combination with a PageView and a BottomNavigationBar, but everytime the page gets switched, a few frames get skipped and the UI freezes for a second.
I've simplified my codebase for this example:
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
void main() => runApp(new Pages());
class Pages extends StatefulWidget {
#override
_PagesState createState() => _PagesState();
}
class _PagesState extends State<Pages> {
PageController _pageController;
int _page = 0;
#override
void initState() {
_pageController = new PageController();
super.initState();
}
void navTapped(int page) {
_pageController.animateToPage(page,
duration: const Duration(milliseconds: 300), curve: Curves.ease);
}
void onPageChanged(int page) {
setState(() {
this._page = page;
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: new Text("CameraTest"),
),
body: PageView(
children: <Widget>[Feed(), Camera(), Profile()],
controller: _pageController,
onPageChanged: onPageChanged,
),
bottomNavigationBar: new BottomNavigationBar(
items: [
new BottomNavigationBarItem(
icon: new Icon(Icons.home), title: new Text("Feed")),
new BottomNavigationBarItem(
icon: new Icon(Icons.camera), title: new Text("Capture")),
new BottomNavigationBarItem(
icon: new Icon(Icons.person), title: new Text("Profile"))
],
onTap: navTapped,
currentIndex: _page,
),
),
);
}
}
class Camera extends StatefulWidget {
#override
_CameraState createState() => _CameraState();
}
class _CameraState extends State<Camera> {
List<CameraDescription> _cameras;
CameraController _controller;
initCameras() async{
_cameras = await availableCameras();
_controller = new CameraController(_cameras[0], ResolutionPreset.medium);
await _controller.initialize();
setState(() {});
}
#override
void initState() {
initCameras();
super.initState();
}
#override
void dispose() {
_controller?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
if (_controller == null || !_controller.value.isInitialized) {
return new Center(
child: new Text("Waiting for camera...", style: TextStyle(color: Colors.grey),),
);
}
return new AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: new CameraPreview(_controller));
}
}
//just placeholder widgets
class Feed extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(child: new Text("Feed"));
}
}
class Profile extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(child: new Text("Profile"));
}
}
There are basically three pages with the middle one showing a camera-preview
(how it's supposed to look), but on switching to the camera and back from it this happens. This is really annoying since it ruins the user experience and is not smooth at all. The lag appears when calling initCameras() or when disposing the camera-controller. I tried using initCameras() in combination with a FutureBuilder, which didn't help at all, and running the method in a seperate isolate, but platform calls seem to be only allowed on the main isolate. It seems a bit weird to me since opening the camera doesn't need too much cpu power, so an async method should be fine. I am aware there is an image-picker plugin, but I want to have the preview in the app directly. I have also considered to run initCameras() on app start, but i don't want to have the camera running all the time when the user is just using another page of the app.
Is there any way to improve upon initCameras() or perhaps use a different implementation to fix the stuttering? I wouldn't even care if it takes a second to load, but i don't want any frame skips.
I followed the example on the bottom of the camera page.
Tested on physical devices as well as emulators on different Android versions.
I have solved a similar issue by adding a delay before initializing the camera:
Future.delayed(Duration(seconds: 1), () {
initCameras();
});
This way the initCameras() is called after the page navigation animation is completed. You can show a CircularProgressIndicator() to make this delay more user friendly.
I am sure there is a more neat way to work around the issue, but this seems to be the simplest solution.
If you want to use image path in the different page than store image path as the global variable, and use it where you want.

Resources