I'm trying to get a list of movies from api but when implementing infinite scroll pagination using ListView ScrollController infinite scroll is not working. I've checked the output from state also it is getting correctly when scroll reaches end of list but not updating in UI. only after i hot reload it shows in the UI.
Here is the Blocfile.
@injectable
class SearchMovieBloc extends Bloc<SearchMovieEvent, SearchMovieState> {
final SearchMovieRepo searchmovierepo;
SearchMovieBloc(this.searchmovierepo) : super(SearchMovieState.initial()) {
on<SearchMovieEvent>((event, emit) async {
final Either<MainFailures, List<MovieModel>> result =
await searchmovierepo.searchmovie(
moviequery: event.moviequery, page: event.page);
log(result.toString());
emit(result.fold(
(failure) =>
state.copyWith(isLoading: false, options: Some(Left(failure))),
(success) => state.copyWith(
isLoading: false,
movies: success,
options: Some(Right(success)))));
});
}
}
SearchMovieState
@freezed
class SearchMovieState with _$SearchMovieState {
const factory SearchMovieState(
{required bool isLoading,
required List<MovieModel> movies,
required Option<Either<MainFailures, List<MovieModel>>> options}) =
_SearchMovieState;
factory SearchMovieState.initial() =>
const SearchMovieState(isLoading: false, options: None(), movies: []);
}
SearchMovieEvent
@freezed
class SearchMovieEvent with _$SearchMovieEvent {
const factory SearchMovieEvent.searchmovie(
{required String moviequery, required int page}) = _SearchMovie;
}
and the UI
class SearchMovieList extends StatefulWidget {
TextEditingController text;
SearchMovieList({
Key? key,
required this.text,
}) : super(key: key);
@override
State<SearchMovieList> createState() => _SearchMovieListState();
It's been two days i've working on this issue hope someone helps me. }
class _SearchMovieListState extends State<SearchMovieList> {
int page = 1;
ScrollController controller = ScrollController();
@override
void initState() {
controller.addListener(() {
if (controller.position.maxScrollExtent == controller.offset) {
page++;
BlocProvider.of<SearchMovieBloc>(context).add(
SearchMovieEvent.searchmovie(
moviequery: widget.text.text, page: page));
}
});
super.initState();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return BlocBuilder<SearchMovieBloc, SearchMovieState>(
builder: (context, state) {
if (state.isLoading) {
return const Center(
child: CircularProgressIndicator(
color: orange,
),
);
} else if (state.movies.isEmpty && widget.text.text.isNotEmpty) {
return const Center(
child: Text(
"No Results to Show",
style: TextStyle(color: grey, fontSize: 25),
),
);
} else if (state.movies.isNotEmpty && widget.text.text.isNotEmpty) {
/* log(state.movies.toString()); */
return ListView.separated(
controller: controller,
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
physics: const BouncingScrollPhysics(),
shrinkWrap: true,
itemBuilder: ((context, itemIndex) {
if (itemIndex < state.movies.length) {
return SearchTile(
ismovie: true,
overview: state.movies[itemIndex].overview!,
id: state.movies[itemIndex].movieid!,
heading: state.movies[itemIndex].title == null
? state.movies[itemIndex].name!
: state.movies[itemIndex].title!,
rating:
state.movies[itemIndex].rating!.toStringAsFixed(1),
image: state.movies[itemIndex].posterPath != null
? "$posterhead${state.movies[itemIndex].posterPath}"
: null,
year: state.movies[itemIndex].releasedate == null ||
state.movies[itemIndex].releasedate!.length < 5
? "_"
: state.movies[itemIndex].releasedate!
.substring(0, 4));
} else {
return const Center(
child: CircularProgressIndicator(color: orange));
}
}),
separatorBuilder: (context, index) => const Divider(
height: 4.0,
),
itemCount: state.movies.length);
} else {
return const SizedBox();
}
},
);
}
}
use the equatable
package or write the ==
operator
manually. However, I have not tried using the freezed package together with equatable
class SearchMovieState extends Equatable {
const SearchMovieState(
{required this.isLoading, required this.movies, required this.options});
final bool isLoading;
final List<MovieModel> movies;
final Option<Either<MainFailures, List<MovieModel>>> options;
@override
List<Object?> get props => [isLoading, movies, options];
}