Raviteja Reddy
Raviteja Reddy

Reputation: 193

Flutter Future <String > cant be assigned to parameter type string

I have a future which gives the a return leadid which is of type string.

Future<String> getleader() async {
    final DocumentSnapshot data = await Firestore.instance
        .collection('groups')
        .document(widget.detailDocument.data['groupId']).get();
    String leadid = data.data['leader'];
  return leadid;
  }

I want to use that value returend here. ListTile( title: Text(getleader()), leading: Text('Leader :'), ),

It says future string cant be assigned to parameter string.

Also i have tried adding a a function to await result as follows

 getdata2() async {
    String lead1= await getleader();

but it too shows the error Future dynamcic is not a subtype of type string

This is where i want the to use the future value

  Widget _memebrprofile() {
    return FutureBuilder(
        future: getleader(),
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            // store the value of the Future in your string variable
            storeValue = snapshot.data;
            return storeValue;
          }
          return Scaffold(
            drawer: newdrawer(),
            appBar: AppBar(
              title: Text('User Details'),
            ),
            body: SingleChildScrollView(
              child: ConstrainedBox(
                constraints: BoxConstraints(),
                child: Column(
                  children: <Widget>[
                    ListTile(
                      title: SelectableText(
                        widget.detailDocument.data["groupId"] ?? '',
                      ),
                      leading: Text('Group Id :'),
                    ),
                    ListTile(
                      title: Text(storeValue),//this is where i want to display the string
                      leading: Text('Leader :'),
                    ),
                    Row(
                      children: <Widget>[
                        Flexible(
                          child: RaisedButton(
                            onPressed: () {
             //this is where i want to use it as a string value to check a certain bool.                if (storeValue == _uid()) {
                                Firestore.instance
                                    .collection('users')
                                    .document(widget.detailDocument.documentID)
                                    .updateData({
                                  'groupId': "",
                                });
                                Navigator.of(context).pop();
                                Navigator.pushNamed(context, assignedTask.id);
                              } else {}
                            },
                            child: Text('Remove user'),
                          ),
                        ),
                        /* Flexible(
                          child:RaisedButton(
                            onPressed: () {

                            },
                            child: Text('Changerole to user'),
                          ),),
                          Flexible(
                            child: RaisedButton(
                              onPressed: () {

                              },
                              child: Text('Changerole to Admin'),
                            ),
                          ),*/
                        Flexible(
                          child: RaisedButton(
                            onPressed: () async {
                              FirebaseAuth auth = FirebaseAuth.instance;
                              final FirebaseUser user =
                                  await auth.currentUser();
                              final userid = user.uid;
                              if (widget.detailDocument.documentID == userid) {
                                Navigator.pushNamed(context, MyProfile.id);
                              } else {}
                            },
                            child: Text('Edit Profile'),
                          ),
                        ),
                      ],
                    ),
                  ],
                ),
              ),
            ),
          );
        });
  }
}

Upvotes: 1

Views: 5009

Answers (3)

Shahmil
Shahmil

Reputation: 341

You can create another function in your StatefulWidget that updates your lead1 using setState()

  String lead1 = "";

  getLeadID() {
    getLeader().then((val) => setState(() {
          lead1 = val;
        }));
  }

.then(val) waits for getLeader() to finish, then allows you to use the returned value val.

Edit:

Set the text in your ListTile to the lead1 variable, like

 ListTile( title: Text(lead1), leading: Text('Leader :'), ),

Then call the getLeadID() funciton in initState(), like this;

class _MyHomePageState extends State<MyHomePage> {

  String lead1 = "";

  @override
  void initState() {
    super.initState();
    getLeadID();
  }

  @override
  Widget build(BuildContext context) {
  //rest of code

Upvotes: 1

timilehinjegede
timilehinjegede

Reputation: 14033

You are getting the error because you are not using a FutureBuilder. Try using a FutureBuilder. You can solve it by wrapping your widget in a FutureBuilder. Check the code below: It works perfectly fine.

    // use a future builder
    return FutureBuilder<String>(
      // assign a function to it (your getLeader method)
      future: getleader(),
        builder: (context, snapshot) {
        if(snapshot.hasData){
          // print your string value
          print(snapshot.data);
          return new ListTile(
              leading: Text('Leader'),
              title: Text(snapshot.data),
              onTap: () {
              }
          );
        } else {
          return Text(snapshot.error.toString());
        }
        }
    );

I hope this helps.

UPDATED As requested to store the value(String) into a variable, check the code below:

// declare your variable 
String storeValue;
    return FutureBuilder<String>(
      // assign a function to it (your getLeader method)
      future: getleader(),
        builder: (context, snapshot) {
        if(snapshot.hasData){
          // store the value of the Future in your string variable
          storeValue = snapshot.data;
          return new ListTile(
              leading: Text('Leader'),
              title: Text(snapshot.data),
              onTap: () {
              }
          );
        } else {
          return Text(snapshot.error.toString());
        }
        }
    );

Upvotes: 1

Peter Haddad
Peter Haddad

Reputation: 80914

Try the following:

          FutureBuilder(
            future: getleader(),
            builder: (context, AsyncSnapshot<String> snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                return ListView.builder(
                    shrinkWrap: true,
                    itemCount: 1,
                    itemBuilder: (BuildContext context, int index) {
                      return ListTile(
                        contentPadding: EdgeInsets.all(8.0),
                        title:
                            Text(snapshot.data),
                      );
                    });
              } else if (snapshot.connectionState == ConnectionState.none) {
                return Text("No data");
              }
              return CircularProgressIndicator();
            },
          ),

Future<String> getleader() async {
    final DocumentSnapshot data = await Firestore.instance
        .collection('groups')
        .document(widget.detailDocument.data['groupId']).get();
    String leadid = data.data['leader'];
  return leadid;
  }

The reason you are getting the above error, is because getleader() returns a Future<String> and Text widget takes a value of type String, therefore using FutureBuilder then you can get the value of the Future and use it inside the Text widget.

Upvotes: 1

Related Questions