Можно ли отправить URL-адрес типа запроса в Future in Flutter? - PullRequest
0 голосов
/ 12 марта 2020

Мне нужно сформировать myUrl внутри Future, связанную с именем пользователя, которое я получил от myfirstpage, я могу получить имя и использовать его в заголовке моей домашней страницы, но я не мог понять, как я могу использовать его в myUrl (вместо "$ _name "),

Возможно, я допустил ошибку, указав на данные с помощью" pushNamed (MyHomePage.routeName); " на самом деле мне не нужно это значение в MyHomePage, оно мне просто нужно для линии формы myUrl, также я попытался сделать значение "_name" глобальным значением и т. д. c просто не удалось выполнить ..

import 'package:flutter/cupertino.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/material.dart';
import 'dart:convert';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';

final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
new GlobalKey<RefreshIndicatorState>();

Future<bool> saveNamedPreference(String name) async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  prefs.setString("name", name);
  return prefs.commit();
}

Future<String> getNamePreferences() async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  String name = prefs.getString("name");
  return name;
}

Payload payloadFromJson(String str) {
  return Payload.fromJson(json.decode(str));
}

String payloadToJson(Payload data) {
  return json.encode(data.toJson());
}

Future<Payload> getData() async{
  String myUrl = 'http://lunedor.pythonanywhere.com/query?username=$_name';
  http.Response response = await http.get(myUrl);
  print(myUrl);
  return response == null ? getData() : payloadFromJson(response.body);
}

class Payload {
  String moviecast;
  String moviedirectors;
  String moviegenre;
  String movieposterurl;
  String movierating;
  String movieruntime;
  String moviesummary;
  String movietitle;
  String moviewriters;
  String movieyear;

  Payload({
    this.moviecast,
    this.moviedirectors,
    this.moviegenre,
    this.movieposterurl,
    this.movierating,
    this.movieruntime,
    this.moviesummary,
    this.movietitle,
    this.moviewriters,
    this.movieyear,
  });

  factory Payload.fromJson(Map<String, dynamic> json) => Payload(
    moviecast: json["Actors"],
    moviedirectors: json["Director"],
    moviegenre: json["Genre"],
    movieposterurl: json["Poster"],
    movierating: json["imdbRating"],
    movieruntime: json["Runtime"],
    moviesummary: json["Plot"],
    movietitle: json["Title"],
    moviewriters: json["Writer"],
    movieyear: json["Year"],
  );

  Map<String, dynamic> toJson() => {
    "moviecast": moviecast,
    "moviedirectors": moviedirectors,
    "moviegenre": moviegenre,
    "movieposterurl": movieposterurl.replaceAll('300.jpg', '900.jpg'),
    "movierating": movierating,
    "movieruntime": movieruntime,
    "moviesummary": moviesummary,
    "movietitle": movietitle,
    "moviewriters": moviewriters,
    "movieyear": movieyear,
  };
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Random Movie',
      theme: new ThemeData(
        primarySwatch: Colors.grey,
      ),
      home: new MyFirstPage(),
      routes: <String, WidgetBuilder>{
        MyHomePage.routeName: (context) => new MyHomePage(),
      },
    );
  }
}

class MyFirstPage extends StatefulWidget {
  @override
  _MyFirstPageState createState() => new _MyFirstPageState();
}

class _MyFirstPageState extends State<MyFirstPage>{
  var _controller = new TextEditingController();

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        backgroundColor: Colors.blueGrey,
        centerTitle: true,
        title: new Text("Please enter your Trakt username",
          style: new TextStyle(
            fontSize: 18.0,
            color: Colors.white,
          ),
        ),
      ),
      body: new ListView(
        children: <Widget>[
          new ListTile(
            title: new TextField(
              controller: _controller,
            ),
          ),
          new ListTile(
            title: new RaisedButton(
                child: new Text("Submit"),
                onPressed:(){setState(() {
                  saveName();
                });
                }),
          )
        ],
      ),
    );
  }
  void saveName() {
    String name = _controller.text;
    saveNamedPreference(name).then((bool committed) {
      Navigator.of(context).pushNamed(MyHomePage.routeName);
    });
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  static String routeName = "/myHomePage";

  final String title;

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

Payload payload;

class _MyHomePageState extends State<MyHomePage> {
  Modal modal = Modal();
  bool isLoading = true;
  String _name = "";

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {loadData();
    WidgetsBinding.instance.addPostFrameCallback((_) => _refreshIndicatorKey.currentState.show());
    getNamePreferences().then(updateName);
    });
  }

  void loadData() async {
    payload = await getData();
    isLoading = false;
    setState(() {});
    print('${payload.movieposterurl.replaceAll('300.jpg', '900.jpg')}');
  }

  void updateName(String name) {
    setState(() {
      this._name = name;
      ValueKey(_name);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      appBar:
      AppBar(
        backgroundColor: Colors.blueGrey,
        title:
        isLoading ? Center(child: CircularProgressIndicator()):Center(
          child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                Center(
                  child: Text('${payload.movietitle}', maxLines: 2, textAlign: TextAlign.center,
                    style: new TextStyle(
                      fontSize: 18.0,
                      color: Colors.white,
                    ),
                  ),
                ),
                Text('${payload.movieyear}' + " - " + _name + " - " + '${payload.movierating}',
                  style: new TextStyle(
                    fontSize: 14.0,
                    color: Colors.black,
                    fontStyle: FontStyle.italic,),
                ),
              ]
          ),
        ),
      ),
      body:
      isLoading ? Center(child: CircularProgressIndicator()):
      RefreshIndicator(
          key: _refreshIndicatorKey,
          onRefresh: () async{payload = await getData();
          isLoading = false;
          setState(() {});
          },
          child: Center(
              child:ListView(
                  shrinkWrap: true,
                  children: [
                    FittedBox(
                      alignment: Alignment.center,
                      child:
                      Image.network('${payload.movieposterurl.replaceAll('300.jpg', '900.jpg')}'),
                    ),
                  ]
              )
          )
      ),
      bottomNavigationBar: isLoading ? Center(child: CircularProgressIndicator()):
      BottomAppBar(
        child: Container(
          color: Colors.grey,
          child: SizedBox(
            width: double.infinity,

            child:
            FlatButton(
              color: Colors.grey,
              textColor: Colors.black,
              onPressed: () {
                modal.mainBottomSheet(context);
              },
              child: Text("Details",
                style: TextStyle(fontSize: 16.0),),
            ),
          ),
        ),
      ),
    );
  }
}

class Modal {
  mainBottomSheet(BuildContext context) {
    showModalBottomSheet(
        context: context,
        builder: (BuildContext context) {
          return SingleChildScrollView(
            child: Column(
              mainAxisSize: MainAxisSize.max,
              children: <Widget>[
                _createTile(
                    context, "Genre: " + payload.moviegenre + "\n" + "Runtime: " + payload.movieruntime, Icons.local_movies,
                    _action),
                _createTile(
                    context, "Director: " + payload.moviedirectors,
                    Icons.movie_creation,
                    _action),
                _createTile(
                    context, "Writer: " + payload.moviewriters,
                    Icons.movie,
                    _action),
                _createTile(
                    context, "Cast: " + payload.moviecast, Icons.chrome_reader_mode,
                    _action),
                _createTile(
                    context, "Summary: " + payload.moviesummary, Icons.recent_actors, _action),
              ],
            ),
          );
        }
    );
  }

  ListTile _createTile(BuildContext context, String name, IconData icon,
      Function action) {
    return ListTile(
      leading: Icon(icon),
      title: Text(name),
      onTap: () {
        Navigator.pop(context);
        action();
      },
    );
  }

  _action() {
    print('action');
  }
}

1 Ответ

1 голос
/ 12 марта 2020

Не совсем уверен, что я получил ваш вопрос, но этого должно быть достаточно для изменения вашего getData() метода, чтобы он принимал String в параметрах, в настоящий момент getData () - это функция верхнего уровня, которая не знает значение _name потому что это частная переменная экземпляра _MyHomePageState

Future<Payload> getData(String name) async{
  String myUrl = 'http://lunedor.pythonanywhere.com/query?username=$name';
  http.Response response = await http.get(myUrl);
  print(myUrl);
  return response == null ? getData() : payloadFromJson(response.body);
}

А затем в вашем методе loadData() передайте правильное значение

void loadData() async {
    payload = await getData(_name);
    isLoading = false;
    setState(() {});
    print('${payload.movieposterurl.replaceAll('300.jpg', '900.jpg')}');
}

И последнее, вы должны добавить «перезагрузить» "logi c при изменении имени

void updateName(String name) {
    setState(() {
      isLoading = true;
      this._name = name;
      ValueKey(_name);
      loadData();
    });
}

Лично я считаю, что переменная Payload должна оставаться внутри вашего класса _MyHomePageState

...