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