从flutter调用方法到gRPC服务时,返回null

时间:2020-07-25 05:31:55

标签: flutter service grpc grpc-dart

我正在尝试使用gRPC开发一个Todo应用。但是,当我尝试从flutter调用方法并打印它时,显示为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 个答案:

答案 0 :(得分:0)

您将得到 null ,因为您的代码异步运行。函数 createTodo()被标记为 async ,因此 res 在您从服务器获得结果之前就已打印出来。要知道未来何时结束,可以将回调函数传递给.then(...)。

要解决您的问题,您需要将打印语句移到回调函数中:

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