On calling a method from flutter to gRPC service , returning null

1.1k Views Asked by At

I am trying to build a todo app in flutter with gRPC. But when I try to call methods from flutter and printing it its showing null.

server.dart

import 'package:grpc/grpc.dart';
import 'package:grpc/src/server/call.dart';

import 'generated/todo.pbgrpc.dart';
//import 'package:grpc_tutorial/src/generated/todo.pbgrpc.dart';

class TodoService extends TodoServiceBase {
  TodoItems todos = new TodoItems(); // TodoItems is generated by Proto

//Create todo
  @override
  Future<TodoItem> createTodo(ServiceCall call, TodoItem request) async {
    // Create a new TodoObject
    TodoItem todoItem = new TodoItem();
    todoItem.text = request.text;
    todoItem.id = todos.$_getList(1).length + 1;

    // Add a new todo Item to our list
    todos.items.add(todoItem);

    // Return a todoItem in accordance with function return typ[e
    return todoItem;
  }

  @override
  Future<TodoItems> readTodos(ServiceCall call, voidNoParam request) async {
    return todos;
  }

  @override
  Stream<TodoItem> readTodosStream(
      ServiceCall call, voidNoParam request) async* {
    // Iterate through all of the todos and 'yield' each todo (returns it to the stream)
    for (var todo in todos.items) {
      yield todo;
    }
  }
}

/**
* gRPC Server
**/
class TodoServer {
  Future<void> main(List<String> args) async {
    final server =
        Server([TodoService()]); // Create a new server from the TodoService
    await server.serve(port: 9000); // Start the server on port 9000
    print('Server listening on port ${server.port}...');
  }
}

main() {
  TodoServer todoServer = new TodoServer();
  todoServer.main([]);
}

main.dart

import 'package:flutter/material.dart';
import 'package:grpc/grpc.dart';
import 'generated/todo.pbgrpc.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  var gprcClient;
  var client;

  Future<TodoItem> createTodo() async{
    final TodoItem todoItem = new TodoItem();
    todoItem.text = "Test 1";
    // Send a request to the server to make the new item
    TodoItem res= await client.createTodo(todoItem);
    // Prints the recieved item
    print("1");
    print(res);
    return res;
  }

  Future<void> readTodo() async{
    print("1");

    final v = new voidNoParam();
    print("hdsbjh");
    // Get a list of todos as a future
    var todos = await client.readTodos(v);
    //print(await client.readTodos(v));
    //print(todos);
    print(todos.items + "item");
    print("hdn");
  }

//  Future<void> readTodoStream() async{
//    print("1");
//
//    final v = new voidNoParam();
//    client.readTodosStream(v).listen((value) {
//      print(value + "val");
//    });
//  }

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

    gprcClient = ClientChannel("10.0.0.2",
        port: 9000,
        options: ChannelOptions(
          credentials: ChannelCredentials.insecure(),
          idleTimeout: Duration(minutes: 1),
        ));

    // client = TodoServiceClient(GrpcClientSingleton().client);
    client = TodoClient(gprcClient);
    print('initial');
    TodoItem res ;
    //print(res);
    createTodo().then(
        (TodoItem val){
          setState(() {
            res = val;
          });
        }
    );
    print(res);
    readTodo();
   // readTodoStream();
    print('final');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          // Here we take the value from the MyHomePage object that was created by
          // the App.build method, and use it to set our appbar title.
          title: Text(widget.title),
        ),
        body: Center(
          child: Text('DEMO APP'),
        ));
  }
}

Output in console
I/flutter ( 8134): initial
I/flutter ( 8134): null   // Here the the val of res should be printed but its showi
I/flutter ( 8134): 1
I/flutter ( 8134): hdsbjh
I/flutter ( 8134): final
1

There are 1 best solutions below

0
On

You are getting null because your code runs asynchronously. The function createTodo() is marked as async, therefore res gets printed before you even get the result from your server. To know when the future has finished, you can pass a callback-function to .then(...).

To fix your problem you need to move your print-statement inside of your callback-function:

TodoItem res;
createTodo().then(
    (TodoItem val){
      // This function gets executed when the result is returned from the server
      setState(() {
        res = val;
        print(res); // If you print it here it works
      });
    }
);
print(res); // <-- This gets called right after createTodo() even it hasn't finished yet