2

In the below code I have passed set state as a function call in a stateless widget how is this possible I know there is nothing wrong with flutter, but its something about the functions in general, I am not getting the basics right can someone plz explain me this concept. Comments are provided for assistance.

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {    //STATEFUL WIDGET
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Demo(function: () {
            setState(() {});      //PASSING SET STATE
          });
        },
      ),
    );
  }
}

class Demo extends StatelessWidget {  //STATE  LESS WIDGET
  final Function function;
  Demo({this.function});

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}
UTKARSH Sharma
  • 698
  • 1
  • 8
  • 17
  • Refer this demo example for passing the value either in State or stateless https://stackoverflow.com/a/61743422/3946958 – Ravindra Kushwaha May 14 '20 at 05:34
  • no, the problem is how can I pass set state call in a stateless widget as stateless widget doesn't know what is set state so how can I pass it as an argument. I know I can pass but (why) is my question – UTKARSH Sharma May 14 '20 at 05:38
  • so is `Demo(function: () { setState(() {}); //PASSING SET STATE });` working or you have any problem with passing such a callback to some other widget? – pskink May 14 '20 at 05:44
  • it's working fine even I have developed a full-fledged app but the question is (how ). – UTKARSH Sharma May 14 '20 at 05:50
  • 1
    have you used any `RaisedButton` / `OutlineButton` / `FlatButton`? they have `onPressed` property - this is exactly the same - you are passing some function to that button and when the click is performed tha button calls that callback function – pskink May 14 '20 at 05:52

3 Answers3

4

setState() is a method inside the State class. In your code you have the following:

   onPressed: () {
          Demo(function: () {
            setState(() {});      //PASSING SET STATE
          });
        },

Here you create an instance of Demo and give it a callback as an argument. Inside that callback, you are calling setState which is a method inside the State class.

Peter Haddad
  • 78,874
  • 25
  • 140
  • 134
  • I am not getting the callback thing plz elaborate a bit how it works in this case. – UTKARSH Sharma May 14 '20 at 06:00
  • @UTKARSHSharma check this https://stackoverflow.com/a/59504089/7015400 – Peter Haddad May 14 '20 at 06:06
  • @UTKARSHSharma @UTKARSHSharma for ex in javascript `function doHomework(subject, callback) { alert(`Starting my ${subject} homework.`); callback(); } doHomework('math', function() { alert('Finished my homework'); });` Here, the function `doHomework` takes a subject variable and function reference `callback`. After the alert appears and you know the subject, then the function (callback) will be called. So basically a callback is a function that is called as a response of something occurring. It can be a response of a click on a button or as a response of retrieving data from the db – Peter Haddad May 14 '20 at 06:11
  • 1
    @UTKARSHSharma so a callback is not called immediately, it is a function that is called in response to something occurring. Thats why its called "callback", you can think about it as call me later. All buttons in flutter, use callback functions and these functions are called in response to when the user clicks the button. All asynchronous code in flutter uses callback and these callbacks are called when the data is retrieved – Peter Haddad May 14 '20 at 06:13
1

In Dart, methods and functions can be passed around just as though they were normal variables and values. In this case, you have passed the setState method from the stateful widget into the constructor of the stateless widget. (Or, more precisely, you have wrapped a call to the stateful widget's setState in an anonymous function and then passed that function to the stateless widget.)

This can be demonstrated more simply in the following way:

class A {
  int x = 0;

  void doThing() {
    x = 5;
  }
}

class B {
  Function f;

  B(this.f);

  void runFunction() {
    f();
  }
}

// ...

A a = A();
B b = B(a.doThing);
b.runFunction();
print(a.x);

// Prints: 5

In this example, the doThing from a is passed into b, which assigns it to b.f. When b calls f, it is the same as calling a.doThing directly, which can be shown by a.x having the updated value after the fact. This is what is known as passing a callback, which is a function passed to another function or object that can then be called without having to reference the passed-in function directly. i.e. b can call a.doThing by calling the callback f() without having to explicitly call a.doThing(). (Note: this is a very simplistic explanation of a callback, and a more detailed explanation goes into the nuance of how the passed function is actually used.)

This is not the same as saying that a.doThing now belongs to b, and b does not now magically have a doThing method. Likewise, when you pass in setValue to a stateless widget, you are not magically granting that widget a state and you are not breaking the rules of Flutter by suddenly being able to call "setState" from a stateless widget any more than if you had passed an instance of the State<MyApp> itself and called stateObj.setState(...) directly (not that I am recommending you do that, of course).

Abion47
  • 22,211
  • 4
  • 65
  • 88
0

Here's another example: we have a class contains a function which require setState and want to use that function from a stateful widget, so I can pass that function by following way.

class Api {
  static bool isLoading = false;
// want to use setState in this function

  static Future<void> getApiResponse({
    required Function(bool) function, //here I setState bool = true so I write bool
  }) async {
    // setState
    function(true);
    try {
      //TODO: some code
      // setState
      function(false);
    } catch (e) {
      //setState
      function(false);
      throw e;
    }
  }
}

// function in stateful widget
Future<void> func1() async {
  await Api.getApiResponse(
    function: (bool value) {
      setState(() {
        Api.isLoading = value;
      });
    },
  );
}
raghav042
  • 679
  • 6
  • 14