Fetching query in Flutter from online HTTP

Viewed 346

What I'm trying to do is fetch query from an HTML so it could be used for search. What I have done so far is made a getMovieSearch() method in my repository, movie_search and movie_search_response models. But so far I haven't been successful to search by title movies in their online query. I searched online but there isn't much info besides this so I followed these steps: https://flutter.dev/docs/cookbook/networking/fetch-data

Here are my folders:

Repository.dart:

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

In model folder -> 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();
}

In model folder also -> 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');
  }
}

And main_page where search functionality is (Updated with Vadims code):

    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 before modifying it:

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,
    );
  }
}

This is my first time trying this so I'm not experienced in it, so anyone who knows if there is a simpler method or how can I fix this error it would be great :). Btw, when I run this code and try the search function in both cases it displays this error:

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

Thanks in advance for the help and tips :D

1 Answers

Looks like here is you got null or wrong type

final suggesstionList = query.isEmpty ? recent : moviess;

Try to print or set a breakpoint like that:

@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,
);
Related