Calling method in separate Class- Flutter - flutter

In my main.dart at the end of a method I call 2 entities, one is within main.dart and works fine, the other is in another Class, _mapItemsExample2.
I have implemented _MyAppState(this._mapItemsExample2); functionality to call it as widget.
void main() {
SdkContext.init(IsolateOrigin.main);
runApp(MaterialApp(
theme: ThemeData(fontFamily: 'DMSans'),
home: MyApp(),
));
}
class MyApp extends StatefulWidget {
MapItemsExample2? _mapItemsExample2;
#override
_MyAppState createState() => _MyAppState(this._mapItemsExample2);
}
class _MyAppState extends State<MyApp> {
final MapItemsExample2? _mapItemsExample2;
_MyAppState(this._mapItemsExample2);
Future<void> intermodalRouter() async{
...
_sendIntermodalDataToSecondScreen(context, mappedValues, dest); //works fine
widget._mapItemsExample2?.showFirstPolylineMapMarkers(deplat, deplong, deplocname);
}
});
}
It will pass data to
class MapItemsExample2 {
void showFirstPolylineMapMarkers(deplat, deplong, deplocname) async {
print('showFirst');
...
But it goes dead and doesn't print or call _showFirstPolylineMapMarkers
I need to call the method to trigger a display of data. No errors showing but even after adding the widget function as suggested it displays nothing and doesnt print readouts
Any guidance appreciated
Thank you
Update
Recieving error in main.dart
2 positional argument(s) expected, but 0 found.
on
final MapItemsExample2 _mapItemsExample2 = MapItemsExample2();
class MapItemsExample2 {
MapItemsExample2(ShowDialogFunction2 showDialogCallback2, HereMapController hereMapController)
: _showDialog2 = showDialogCallback2,
_hereMapController = hereMapController {
void showFirstPolylineMapMarkers(deplat, deplong, deplocname) async {
print('showFirst');
Have tried adding parameters in but they are not recognised

You are using the ?. null-aware operator when calling showFirstPolylineMapMarkers(..), so it will only call it if widget._mapItemsExample2 is not null. Have you checked whether it is null or not at the time you're making this call?
In your code it is apparent that no instance of _mapItemsExample2 is being passed into MyApp() when you call it from main(), since the parameter list is empty. You need to create an instance of it and pass it into MyApp, or get access to a previously created instance to pass in. I don't have enough code to give you a more specific answer.

Related

Flutter - How to call functions (and variables) between stateful widgets?

I have this function in a widget (homescreen):
void toggleRecording() async {
// HERE IS THE CONFUSION I GUESS
_isRecording = !_isRecording;
recorder = SoundStream(isRecording: _isRecording);
//recorder.toggleRecording(_isRecording);
setState(() {
_isRecording = recorder.isRecording;
});
if (_isRecording) {
startTimer();
_stopwatch.start();
} else {
stopTimer();
_stopwatch.stop();
}
}
It needs to call (trigger) another function in my recorder class:
void toggleRecording() async {
widget.isRecording ////// currently being passed as an argument from homescreen
? {_recorder.stop, await save(_micChunks, 44100)}
: _recorder.start;
}
Also, the boolean variable _isRecording is present in both the classes. How do I sync the state?
In your situation passing reference of function through widgets will work. However best practice of this will be using provider package.
Managing functions from provider will allow you to control functions from all pages.
If you change a variable you can call notifylistener() function inside your provider function. So that you can change state of widget.
I will try to explain it in a glance however this is an important subject of flutter.
Here is my folder structure
At provider folder we define our provider classes.
Firstly i define class which extends changeNotifier class. This is what make this class provider.
Side note: notifyListener() function here calls setState of every widget if you use any variables inside that class and this is what you are searching for.
Then i import it into my main.dart file or whatever file you want. Only condition is being above the widget that you will use provider at.
At last you can use your function at everywhere if you import provider package and define your provider like i did in this code.
At last here is the visualized stucture of provider package.
I wish i explained it well. There is more about it on youtube.
Pass the function to other widget
using Function keyword
Say ContentWidget is your child and ParentWidget is parent
class ParentWidget extends StatefulWidget {
//Do Something
void onSomeFunction()
{
ContentWidget(onTimerUpdate:onTimerClosed)
}
void onTimerClosed()
{
//Perform Operation on Timer Change
}
}
class ContentWidget extends StatefulWidget {
final Function onTimerUpdate;
ContentWidget({
Key key,
#required this.onTimerUpdate,
}) : super(key: key);
void onAnyActionFromChild()
{
widget.onTimerUpdate() //Note () can have any param or can be null
}

Multiple questions related to Flutter basic

I am coming from React and trying to understand Flutter. There are some differences between dart vs JS and React vs Flutter. However, it seems a bit similar to each other. However, there is some confusion toward Flutter.
void
It does not return the value. Therefore, it is used to void main(). Does it mean like the function 'main()' will be executed and I will never be able to reuse void main()?
<>
In the code, I have here
class LoginScreen extends StatefulWidget {
createState() {
return new LoginScreenState();
}
}
class LoginScreenState extends State<LoginScreen> {
Widget build(context) {
return Container(
margin: EdgeInsets.all(20.0),
child: Column(
children: [
emailField(),
// passwordField(),
// submitButton(),
],
));
}
}
I can see that State<LoginScreen> is related to class LoginScreen. It is an extension of the LoginScreen State?
Future<int> successor = future.then((int value) {
},
However, in here Future <----- I do not understand why it has to state 'int' in this code. What is the proper use of <>?
Stateful vs Stateless
Can I just use the Stateful all the time even if I do not have any state like React? Where there is no difference?
You need to learn basic dart.
void main() is same as main(). The only difference is declaring the return type. main() is called only once by the flutter engine.
Read about generics. <> is the called the diamond operator and is used to specify the type of something. Future<int> means the function will return something in future and it will strictly be of int type. If you don't specify the type flutter will treat it as dynamic.
You can use stateful classes if you are using state management packages like provider or rxdart to maintain state.
class LoginScreen extends StatefulWidget {
createState() {
return new LoginScreenState();
}
}
enter code here
changed to
class LoginScreen extends StatefulWidget {
LoginScreenState createState()=>LoginScreenState();
}
}
enter code here
Stateful vs Stateless`enter code here`
stateful has state object and stateless has no state object.using stateful you can changes widget data .on other hand in stateful you cant

Flutter: A variable passed to the next screen becomes null

I want to pass a variable to the next screen but it becomes null in the next screen. what am I wrong with this? My code is like below.
first_screen.dart
onTap: () {
print(doc); // Prints out Instance of `DocumentSnapshot` on log
Navigator.of(context).pushNamed('/second', arguments: doc);
},
second_screen.dart
class SecondScreen extends StatefulWidget {
final DocumentSnapshot doc;
SecondScreen({
this.doc,
});
#override
State<StatefulWidget> createState() {
return _SecondScreenStateState();
}
}
class _SecondScreenState extends State<SecondScreen> {
#override
void initState() {
super.initState();
print(widget.doc); // Prints out null here
}
I tried with othe data types but all variables become null in the next screen.
You have to pass argument like this:
Navigator.of(context).pushNamed('/second', arguments: doc);
for you is true but, use the ModalRoute.of() method to returns the current route with the arguments like this:
final doc = ModalRoute.of(context).settings.arguments as String;
I assumed that doc is String.
If you're sharing data between widgets (screens) try looking at InheritedWidget.Take a look at https://www.youtube.com/watch?v=1t-8rBCGBYw. You can also look at state management packages like provider which is pretty easy to understand or a bloc. These will save you in the long run.

Where do I put commands that run once at beginning?

I really miss C programming. Flutter is quite confusing.
Here is the problem:
We have a function within the Stateful class Home. That creates a page called myMenu.
class Home extends StatefulWidget {
myMenu createState() => myMenu();
}
class myMenu extends State<Home>
{
void myProblemFunction(String stringItem) async {
final db = await myDatabaseClass.instance.database;
...
}
Whenever myProblemFunction runs, it will instantiate a new database instance.
I just want to put this command once (i.e.:
final db = await myDatabaseClass.instance.database
) anywhere in my document (this is my main.dart file (by the way). Now, I could put it in the initState() - sure.. but that's a headache, because a) I would have to make it async, and I feel that will cause me problems, and b) declaring final db... (etc) in the initState() will not make the db variable visible to my functions.
What do I do?
what are the elements in myMenu Class that are triggered? Should I put this function inside the widget build method? But surely if the widget is refreshed, then this function will also be called (again) - I just want to call it once.
Thanks
you can use FutureBuilder
example:
FutureBuilder(
future: myDatabaseClass.instance.database,
builder: (BuildContext context,AsycnSnapshot snapshot){
//your code here
},
)
this will only load the Future once when the widget is built.
put your code that you want to run only once in initState():
#override
void initState() {
super.initState();
// TODO code you want to run only once
}

Unable to initialize variables before build?

I am working on app which requires me to fetch data from the server (in my case a simple firebase real time database) and store the fetched data in map before the build method is called since i will be needing to use the map in the build method.
Here I have tried to recreate the error using a test code.
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
class Test extends StatefulWidget {
#override
Map<String, dynamic> livefeed;
State<StatefulWidget> createState() {
// TODO: implement createState
return TestState();
}
}
class TestState extends State<Test> {
#override
void initState() {
http
.get('HERE GOES THE URL FOR THE DATABASE ,CANT DISCLOSE')
.then((http.Response response) {
widget.livefeed = json.decode(response.body);
print(widget.livefeed);
print(widget.livefeed.length);
});
// TODO: implement initState
super.initState();
}
#override
Widget build(BuildContext context) {
return Container(
child: Text(widget.livefeed.toString()),
);
}
}
The Console print :
{-Lh7FJV_7FIXgEUUS3Is: {skill: Andriod dev, target: Just Entered The Lab.,
username: test}, -Lh7RKgw3K2ZuKjrBZd2: {skill: Andriod dev, target: Just
Entered The Lab., username: test}}
I/flutter ( 7078): 2
Yet my UI shows null when i try to display the map on the screen
inside the build method.
I am aware that initState() method is called before the Build() method yet initialization fails, the debug console confirms that data is being fetched yet it fails to be printed on the screen implying build is being called before the values are initialized .
You need to put this inside a setState method
widget.livefeed = json.decode(response.body);
And ofcourse you need to handle what to show while the widget.livefeed is null. As you said even initState() method is called before the Build() method, http.get() is an async function. You can't assure that it will finish before build method is called BECAUSE IT IS AN ASYNC FUNCTION.
You can handle it like this
Text(widget.livefeed!=null?widget.livefeed.toString():'some default text like loading...'),