【问题标题】:Fetching query in Flutter from online HTTP从在线 HTTP 获取 Flutter 中的查询
【发布时间】:2021-09-12 17:27:19
【问题描述】:

我要做的是从 HTML 中获取查询,以便将其用于搜索。到目前为止,我所做的是在我的存储库、movie_search 和 movie_search_response 模型中创建了一个 getMovieSearch() 方法。但到目前为止,我还没有成功在他们的在线查询中按标题电影搜索。我在网上搜索,但除此之外没有太多信息,所以我按照以下步骤操作:https://flutter.dev/docs/cookbook/networking/fetch-data

这是我的文件夹:

Repository.dart:

  Future<http.Response> getMovieSearch() {
    return http.get(Uri.parse(
        'https://api.themoviedb.org/3/search/movie?api_key=89eef3426d167c3c8145a257ebe68357&query='));
  }

在模型文件夹中 -> search_movie.dart:

class MovieSearch {
  final int id;
  final String title;
  final String backPoster;
  final String poster;
  final String overview;
  final double rating;

  MovieSearch(this.id, this.title, this.backPoster, this.poster, this.overview,
      this.rating);

  MovieSearch.fromJson(Map<String, dynamic> json)
      : id = json["id"],
        title = json["title"],
        backPoster = json["backdrop_path"],
        poster = json["poster_path"],
        overview = json["overview"],
        rating = json["vote_average"].toDouble();
}

也在模型文件夹中 -> movie_search_response.dart:

import 'dart:convert';
import 'package:movie_app/model/movie_search.dart';
import 'package:http/http.dart' as http;

Future<MovieSearch> getMovieSearch() async {
  final response = await http.get(Uri.parse(
      'https://api.themoviedb.org/3/search/movie?api_key=89eef3426d167c3c8145a257ebe68357&query='));

  if (response.statusCode == 200) {
    // If the server did return a 200 OK response,
    // then parse the JSON.
    return MovieSearch.fromJson(jsonDecode(response.body));
  } else {
    // If the server did not return a 200 OK response,
    // then throw an exception.
    throw Exception('Failed to load movies');
  }
}

搜索功能所在的 main_page(已使用 Vadims 代码更新):

    import 'package:eva_icons_flutter/eva_icons_flutter.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:movie_app/model/movie_search.dart';
import 'package:movie_app/arch/get_movies.dart';
import 'package:movie_app/model/movie.dart';
import 'package:movie_app/model/movie_response.dart';
import 'package:movie_app/model/movie_search_response.dart';
import 'package:movie_app/view/now_playing_movie.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:movie_app/view/now_playing_tv.dart';
import 'package:movie_app/view/top_movies.dart';
import 'package:movie_app/view/top_tvs.dart';
import '../style/style.dart';

class HomePageMovie extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

Future<MovieSearch> movieSearch;

void initState() {
  initState();
  movieSearch = getMovieSearch();
  movies..getMovies();
}

class _HomePageState extends State<HomePageMovie> {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 2,
      child: Scaffold(
        backgroundColor: Color(0xFF151C26),
        appBar: AppBar(
          backgroundColor: Color(0xFF151C26),
          title: Row(
            mainAxisAlignment: MainAxisAlignment.start,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              SvgPicture.asset(
                logo,
                height: 195,
              ),
            ],
          ),
          actions: <Widget>[
            IconButton(
                onPressed: () {
                  showSearch(context: context, delegate: DataSearch());
                },
                icon: Icon(
                  EvaIcons.searchOutline,
                  color: Colors.white,
                ))
          ],
          titleSpacing: 0.0,
          bottom: PreferredSize(
            preferredSize: Size.fromHeight(75.0),
            child: TabBar(
                indicatorColor: Color(0xFFf4C10F),
                indicatorWeight: 4.0,
                unselectedLabelColor: Colors.white,
                labelColor: Colors.white,
                tabs: [
                  Tab(
                    icon: Icon(Icons.movie),
                    child: Text(
                      "Movies",
                      style: TextStyle(
                          color: Colors.white,
                          fontWeight: FontWeight.bold,
                          fontSize: 14.0),
                    ),
                  ),
                  Tab(
                    icon: Icon(Icons.live_tv),
                    child: Text(
                      "TV Shows",
                      style: TextStyle(
                          color: Colors.white,
                          fontWeight: FontWeight.bold,
                          fontSize: 14.0),
                    ),
                  )
                ]),
          ),
        ),
        body: TabBarView(
          children: [
            ListView(
              children: <Widget>[NowPlayingMovies(), BestMovie()],
            ),
            ListView(
              children: <Widget>[
                NowPlayingTV(),
                BestTV(),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

//Search

class DataSearch extends SearchDelegate<String> {
  final dummyQuery = [
    "Movie 1",
    "Movie 2",
    "Movie 3",
    "Movie 4",
    "Movie 5",
    "Movie 6",
    "Movie 7",
    "Movie 8",
    "movie 9",
    "movie 10",
    "movie 11",
    "movie 12",
    "movie 13",
  ];
  final moviess = [movieSearch];
  final recent = [];

  @override
  List<Widget> buildActions(BuildContext context) {
    return [
      IconButton(
          icon: Icon(Icons.clear),
          onPressed: () {
            query = "";
          })
    ];
  }

  @override
  Widget buildLeading(BuildContext context) {
    return IconButton(
        icon: Icon(Icons.arrow_back),
        onPressed: () {
          close(context, null);
        });
  }

  @override
  Widget buildResults(BuildContext context) {
    //nesta
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    final suggesstionList = query.isEmpty ? recent : moviess;

    return SizedBox(
      height: 120,
      child: ListView.builder(
        itemBuilder: (context, index) => ListTile(
          leading: Icon(Icons.movie),
          title: RichText(
              text: TextSpan(
                  text: suggesstionList[index].substring(0, query.length),
                  style: TextStyle(
                      color: Colors.black, fontWeight: FontWeight.bold),
                  children: [
                TextSpan(
                    text: suggesstionList[index].substring(query.length),
                    style: TextStyle(color: Colors.grey))
              ])),
        ),
        itemCount: 10,
      ),
    );
  },
  itemCount: suggesstionList != null ? suggesstionList.length : 1,
);

} }

修改前的DataSearch:

class DataSearch extends SearchDelegate<String> {
  final dummyQuery = [];
  final moviess = [movieSearch];
  final recent = [];

  @override
  List<Widget> buildActions(BuildContext context) {
    return [
      IconButton(
          icon: Icon(Icons.clear),
          onPressed: () {
            query = "";
          })
    ];
  }

  @override
  Widget buildLeading(BuildContext context) {
    return IconButton(
        icon: Icon(Icons.arrow_back),
        onPressed: () {
          close(context, null);
        });
  }

  @override
  Widget buildResults(BuildContext context) {
    //nesta
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    final suggesstionList = query.isEmpty ? recent : moviess;

    return ListView.builder(
      itemBuilder: (context, index) => ListTile(
        leading: Icon(Icons.movie),
        title: RichText(
            text: TextSpan(
                text: suggesstionList[index].substring(0, query.length),
                style:
                    TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
                children: [
              TextSpan(
                  text: suggesstionList[index].substring(query.length),
                  style: TextStyle(color: Colors.grey))
            ])),
      ),
      itemCount: 10,
    );
  }
}

这是我第一次尝试这个,所以我没有经验,所以任何知道是否有更简单的方法或如何解决这个错误的人都会很棒:)。顺便说一句,当我在这两种情况下运行此代码并尝试搜索功能时,它都会显示此错误:

    The following NoSuchMethodError was thrown building:
The method 'substring' was called on null.
Receiver: null
Tried calling: substring(0, 1)

提前感谢您的帮助和提示:D

【问题讨论】:

    标签: json flutter dart


    【解决方案1】:

    看起来你输入了 null 或错误的类型

    final suggesstionList = query.isEmpty ? recent : moviess;
    

    尝试打印或设置这样的断点:

    @override
      Widget buildSuggestions(BuildContext context) {
        final suggesstionList = query.isEmpty ? recent : moviess;
        return ListView.builder(
      itemBuilder: (context, index) {
       if (suggesstionList == null) {
        print('suggesstionList is null');
        print('query is $query');
        print('recent is $recent');
        print('moviess is moviess');
        return Text('Oops, something went wrong');
       }
       print('suggesstionList type: ${suggesstionList.runtimeType}');
       print('suggesstionList length: ${suggesstionList.length}');
       return ListView.builder(
       //// Here is your code
       );
      }
      itemCount: suggesstionList != null ? suggesstionList.length : 1,
    );
    

    【讨论】:

    • 这是我添加您的代码时遇到的错误:˝══╡ 小部件库╞══════════════════ ═════════════════════════════════════════以下断言被抛出>(脏,依赖项:[_LocalizationsScope-[GlobalKey#19689],_InheritedTheme],状态:_SearchPageState#d2012):'package:flutter/src/widgets/basic.dart':断言失败:第 7419 行 pos 15: 'child != null': 不正确。˝
    • 我的错,我忘了在返回 ListView.builder 之前添加 2 个括号,现在的错误是:引发了另一个异常:NoSuchMethodError:在 null 上调用了方法“子字符串”。所以它是同样的错误:(
    • @Don 我已经更新了答案,请查看 :)
    • 这是我在更新后得到的错误,如你所说:没有抛出异常:'package:flutter/src/rendering/sliver_multi_box_adaptor.dart':断言失败:第 544 行 pos 12:'child .hasSize': 不正确。
    猜你喜欢
    • 2022-11-08
    • 2011-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-19
    • 2023-04-03
    • 2020-10-10
    • 1970-01-01
    相关资源
    最近更新 更多