1

我正在尝试使用 gRPC 构建一个待办事项应用程序。但是当我尝试从颤振中调用方法并打印它时,它显示为空。

服务器.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'),
        ));
  }
}

控制台输出
I/颤动(8134):初始
I/flutter (8134): null // 这里应该打印 res 的 val 但它的显示
我/颤振(8134):1
我/颤振(8134):hdsbjh
我/颤振(8134):最终
4

1 回答 1

1

你得到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
于 2020-07-26T18:17:05.293 回答