Usama Mughal
Usama Mughal

Reputation: 127

The argument type 'Future<dynamic>' can't be assigned to the parameter type 'String'

I've seen similar questions that were asked in regards to this but my problem is a little different in that I'm keeping my application modular so I have defined the following method in a different dart file(Simply a class, not a widget):

Future getProfile() async {
return await usersCollection.doc(uid).get().then<dynamic>((DocumentSnapshot snapshot) async {
  print(snapshot.data()['name']);
  if(snapshot.data()['name'] == null){
    print("No name exists");
  }
  else {
    return snapshot.data()['name'];
  }
});

And I'm trying to use it's value on my home widget:

import 'package:flutter/material.dart';
import 'package:carpoolapp/services/auth.dart';
import 'package:carpoolapp/services/database.dart';
import 'package:firebase_auth/firebase_auth.dart';

class Home extends StatefulWidget {

  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  final AuthService _auth = AuthService();

  User user = FirebaseAuth.instance.currentUser;

  DatabaseService db = DatabaseService(uid: FirebaseAuth.instance.currentUser.uid);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: Colors.redAccent,
        appBar: AppBar(
          title: Text('Signed in'),
          backgroundColor: Colors.blueAccent,
          elevation: 0.0, //no drop shadow
          actions: <Widget>[
            FlatButton.icon(
                onPressed: () async {
                  await _auth.signOutUser();
                },
                icon: Icon(Icons.person),
                label: Text('logout')),
          ],
        ),
        body: Text(db.getProfile()), // Error is here
        //body: UserTile(user: FirebaseAuth.instance().getCurrentUser()),
    );
  }
}

How do I go about making this work without sacrificing the modularity?

Upvotes: 5

Views: 32553

Answers (2)

krishnaacharyaa
krishnaacharyaa

Reputation: 25140

I would like to add to @Pradyot Prakash's answer with some actual code:

Use the following code snippet as an example to achieve the modularity

 @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
          child: FutureBuilder<DocumentSnapshot<Map<String, dynamic>>>(

           future: getProfile() // 👈 Your future function here

        builder: (_, snapshot) {
          if (snapshot.hasError) return Text('Error = ${snapshot.error}');
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Text("Loading");
          }
          Map<String, dynamic> data = snapshot.data!.data()!;
          return Text(data['name']); //👈 Your valid data here
        },
      )),
    );
  }

Upvotes: 1

Pradyot Prakash
Pradyot Prakash

Reputation: 136

By seeing

The argument type 'Future<dynamic>' can't be assigned to the parameter type 'String'

this and

Text(db.getProfile())

the issue is db.getProfile() is an async method. That's why its telling Future can't be assigned to String since Text widget data key is of type String not Future<String>.

You can use FutureBuilder in the body and use the snapshot in the Text which will have the String value.

Upvotes: 12

Related Questions