I want to get Future
return value and use it like variable.
I have this Future
function
Future<User> _fetchUserInfo(String id) async {
User fetchedUser;
await Firestore.instance
.collection('user')
.document(id)
.get()
.then((snapshot) {
final User user = User(snapshot);
fetchedUser = user;
});
return fetchedUser;
}
And I want get value like so
final user = _fetchUserInfo(id);
However when I tried to use like this
new Text(user.userName);
Dart doesn't recognize as User
class. It says dynamic
.
How Can I get return value and use it?
Am I doing wrong way first of all?
Any help is appreciated!
You can simplify the code:
Future<User> _fetchUserInfo(String id) async {
User fetchedUser;
var snapshot = await Firestore.instance
.collection('user')
.document(id)
.get();
return User(snapshot);
}
you also need async/await to get the value
void foo() async {
final user = await _fetchUserInfo(id);
}
use like this
var username;
dbHelper.getUsers().then((user) {
username = user.getName;
});
this function returns future value
dbHelper.getUsers()
it is written like this
getUsers() async { .... }
To add a little more detail on the original question from Daibaku which might help clarify using Futures in Flutter/dart, user
was:
final user = _fetchUserInfo(id);
Without letting compiler infer type, that would be:
final Future<User> user = _fetchUserInfo(id);
Get & Use a Future Value
Daibaku asked how to get the return value of user
& use it.
To use user
in a Widget, your widget must watch/observe for changes, and rebuild itself when it does.
You can do this manually with a lot of boilerplate code, or you could use FutureBuilder
, which has done this for you:
FutureBuilder(future: user, builder: (context, snapshot)
{
if (snapshot.hasData) return Text(snapshot.data.userName);
return Container(width: 0.0, height: 0.0,);
}
More explicitly, you could write the above as:
FutureBuilder<User>(future: user, builder: (context, AsyncSnapshot<User> userSnapshot)
{
if (userSnapshot.hasData) return Text(userSnapshot.data.userName);
return Container(width: 0.0, height: 0.0,);
}
FutureBuilder
in the above example, synchronously (i.e. immediately) returns a zero width/height Container Widget, but also attaches an observer to your future user
, to know when Future data arrives.
When user
is eventually updated with "data", FutureBuilder
's observer is notified and it calls setState()
, which starts a rebuild of itself. Now that snapshot.hasData
is true
, Text(snapshot.data.userName)
is returned instead of the empty Container.
If you weren't using user
within the synchronous world of Widget Element tree building and just wanted to print out the value for debugging you could attach an observer using then
:
user.then((u) => print(u.userName));
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
class ThreadExample implements Callable<String>{
@Override
public String call() throws Exception {
// TODO Auto-generated method stub
return "Ashish";
}
}
public class FutureThreadExample {
public static void main(String a[]) throws InterruptedException, ExecutionException {
ExecutorService executorService=Executors.newFixedThreadPool(1);
List <Future<String>>objList=new ArrayList<Future<String>>();
for(int i=0;i<10;i++) {
Future<String> obj=executorService.submit(new ThreadExample());
objList.add(obj);
}
for( Future<String> fut:objList) {
System.out.println(fut.get());
}
executorService.shutdown();
}
}