Аргументом класса FutureBuilder в будущем является асин c функция с аргументами - PullRequest
0 голосов
/ 19 апреля 2020

Я занимаюсь разработкой мобильного приложения Flutter, которое использует API Google. На одном из экранов моего приложения я хочу позволить пользователю вводить место (город, адрес, ...) и вызывать API Google Адресов, чтобы сгенерировать список предложений на основе ввода пользователя. Всякий раз, когда ввод текста изменяется, выдается новый запрос GET.

Для обработки пользовательского ввода я использую TextEditingController, и для лучшего пользовательского опыта я хочу использовать класс FutureBuilder, чтобы при загрузке показывать загрузчик данные не готовы. Это код:

import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';

class Info extends StatefulWidget {
  static const routeName = '/info';

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

class _InfoState extends State<Info> {
  final controller = TextEditingController();

  @override
  void initState() {
    // Start listening to changes.
    controller.addListener(buildPredictionList);
    super.initState();
  }

  @override
  void dispose() {
    // Clean up the controller when the widget is disposed.
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Info'),
      ),
      body: Column(
        children: <Widget>[
          TextField(
            controller: controller,
          ),
          Container(
            height: 200,
            child: buildPredictionList(),
          ),
        ],
      ),
    );
  }

  Widget buildPredictionList() {
    return FutureBuilder(
      future: fetchPredictions,                      // <-- Error! fetchPredictions expects a parameter!
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return ListView.builder(
            itemCount: snapshot.data.length,
            itemBuilder: (context, index) {
              Prediction pred = snapshot.data[index];
              return Card(
                child: ListTile(
                  leading: Icon(Icons.pin_drop),
                  title: Text('${pred.description}'),
                ),
              );
            },
          );
        } else if (snapshot.hasError) {
          return Text('${snapshot.error}');
        }
        return CircularProgressIndicator();
      },
    );
  }
}

class Prediction {
  final String placeId;
  final String description;

  Prediction({this.placeId, this.description});

  factory Prediction.fromJson(Map<String, dynamic> json) {
    return Prediction(
      placeId: json['place_id'],
      description: json['description'],
    );
  }
}

Future<List<Prediction>> fetchPredictions(String query) async {
  const GOOGLE_API_KEY = '...';
  final lat = 40.758058;
  final lng = -73.985626;
  final radius = 2000;
  final lang = 'en';
  var url =
      'https://maps.googleapis.com/maps/api/place/autocomplete/json?input=$query&key=$GOOGLE_API_KEY&location=$lat,$lng&radius=$radius&language=$lang&strictbounds=true';

  final response = await http.get(url);

  if (response.statusCode == 200) {
    var predictionsJson = json.decode(response.body)['predictions'] as List;
    List<Prediction> predictions = predictionsJson
        .map((predictionJson) => Prediction.fromJson(predictionJson))
        .toList();
    return predictions;
  } else {
    throw Exception('Failed to fetch Predictions');
  }
}

Моя асинхронная c функция fetchPredictions ожидает аргумент, который является строкой запроса, используемой для запроса GET (таким образом, адрес ввода, город, ...). Но я не могу обернуть это в анонимную функцию, потому что аргумент future ожидает тип возврата Future.

Заранее спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...